Flax: a good source of Selenium
In this talk, we discuss the design and implementation of "Flax", a purely functional wrapper around the Selenium web testing library. Flax is written in Scala and allows you to create web tests within an "Action" Monad. By making use of Scala's for-comprehensions, Flax tests read like a set of test instructions, but with the benefits of a functional approach.
The talk describes Flax's Action Monad in detail, showing how it is a stack of Either, Reader, Writer and Task. Each of these effects has a specific purpose in Flax's use as a tool for constructing browser-based tests.
Initially, in Flax, we wanted to just do something quick-and-dirty - FP is nice, but for a testing library, do we really need it? However, a number of design problems quickly arose. We'll talk about these issues and how we realized that the purely functional approach was the only sensible way forward.
A key problem we encountered with the functional approach was that we no longer able to use stack traces to identify where a test failed. To address this, we used the Writer Monad to track the actions performed. The actions are tracked as a tree of operations, which lets us group higher-level actions as a tree of lower-level actions. This is particularly useful for structuring browser tests, as often a specification of desired behavior can translate into a long sequence of individual steps.
Outline/Structure of the Talk
The structure follows our experience designing the library for the needs of test automation on an existing Scala codebase.
- Do we need FP?
We start by describing the initial concept for the library - something quick and dirty that just let us easily use Selenium in the Specs2 testing framework. We talk about the design problems we encountered and why we turned to FP.
- The Action Monad
In this section, we describe the stack of effects that make up the Action Monad, and the role each effect has in our testing library.
- Recovering from lost stack traces
We describe how the purely functional approach lost our stack traces, and how we not only recovered from this, but ended up with something more useful.
We wrap up with some final thoughts about library design in FP.
The aim is to teach the audience about functional library design, by providing a real-world example. The audience will learn the process of modeling a computation by describing it in terms of the effects it exhibits. We aim to show some uses of Reader and Writer - in our experience, many developers new to FP struggle to see the use cases for these data types.
Programmers who have used several of the common Monads, but who haven't seen the need for Reader and Writer in practice. Programmers who have written FP code but haven't had the experience of designing a reusable library using FP principles.
Prerequisites for Attendees
Some exposure to programming in a language like Scala or Haskell. Familiarity with use of common Monads (Either and IO) and do-notation / for-comprehensions.