I have been working on a tool called Lucid which is, in many ways, almost a direct port of the popular tool Cucumber. I do believe tools with humanizing and fluent interfaces are key to the future of testing. Here I’ll explain a little of the basis behind Lucid.
One obvious question might be: if there are already tools out there — like Cucumber, SpecFlow, Behat, Lettuce — why choose to come up with another one? Beyond that, why create one that is so closely aligned with an existing solution?
Part of the answer is that I ultimately want to provide a more configurable framework than I currently see with some of the existing solutions. I also want to incorporate more functionality into Lucid than is currently directly available with other tools. But, beyond even those concerns, I also want to have a tool that matches how I think about testing. The name “lucid” refers to the approach of “lucid testing.” That, to me, simply sounds better than a (let’s admit it) ridiculous sounding name like “Cucumber.” I also want to match up concepts a bit better during tool operation. For example, Cucumber refers to “snippet” whereas I prefer “matcher”.
The Lucid Ecosystem
But what actually is Lucid?
- Lucid can be thought of as a business requirements specification framework. In this way Lucid would be used for capturing business requirements and providing a way to create a ubiquitous language.
- Lucid can also be thought of as a test specification framework. In this way Lucid is used for capturing tests in the form of a Test Description Language (TDL) that matches the ubiquitous language.
- Lucid can also be thought of as a TDL execution framework. In this way Lucid is used to provide a structure that allows for tests to be validated against an application.
Or Lucid can be thought of as all of these things together. Lucid is an approach. Lucid is also a tool. Lucid is also an interface. These, at least, are my immediate goals for it.
Let’s take the first two in that list: the idea that Lucid is a specification framework. In this context the goal for the Lucid framework is to be output-focused, condition-based, and example-driven. A lot of what that actually means will come out in further posts. Suffice it to say that I believe tools like this should attempt to impart good requirement and test design practices and encode those as part of its operation.
Lucid is also predicated on a few core ideas:
- Requirements can be written as tests.
- Testing is a design activity.
In order to adhere to these ideas, as well as to satisfy the above-mentioned goals, Lucid uses a lightweight structure to do the following:
- Write examples of the behavior that users want.
- Allow those examples to be readable in business domain terms.
- Allow those examples to be drivers to development.
- Allow those examples to be executable as tests whether manually or via automation.
We all know that the idea of “testing takes too long” is really a way of saying that “fixing the problems in the application takes too long.” The idea of “testing as a design activity” is to put tests where they stand the best chance of finding an issue at the most responsible time. The most responsible time, of course, is when we are discussing what to build in the first place.
In this way we take the view of lean software development and lean testing. This means we take an options-based approach. It’s not all or nothing; it’s not either-or. What it means is this:
We do the most responsible things we can do, at the earliest times we can do them, consistent with our skills and experience, consistent with the values we have as a team regarding how our work deliverables are effective/efficient, and consistent with the idea of getting the most important issues raised in the most timely manner.
This kind of approach will show you something:
This will tell you a lot about how creative, flexible, adaptive and innovative your team can be, while still being responsible to the needs of the business.
What we’re really talking about here is building up a shared understanding of quality and that’s what I believe that tools like Cucumber, SpecFlow, and Lucid can help with. But where and how do we encode that understanding? That goes back to what I said before: requirements as tests. Specifically, you write actionable requirements in the language of a test. These tests are focused on business intent and task implementation, as opposed to UI level implementation concerns.
I believe all of this is most effectively done by adhering to a Test Description Language (TDL).
As a general note, you always have some form of TDL. You are always describing your tests. You can’t help but do so. The question is what principles, values, and idioms guide your expression and what structuring elements you use as part of your TDL to help provide reminders of that expression. Once you consider that, you then get into more high-level concepts that also speak to how you write tests. Lucid, like other such tools, allows you to use a structured format to write those tests, currently based on the Gherkin language. Note, however, that Gherkin just provides a structuring element — based on a Given/When/Then motif. Gherkin does not help you create a ubiquitous language and it most certainly does not provide a TDL.
We all know that a tool is just a tool. It’s not going to make you better at crafting tests. However, a tool can guide expression. When people find they keep “fighting” a tool due to it not matching their model of how they want to express, that tells you something about the tool. It doesn’t tell you that it’s a bad tool. It tells you that it may not be the most effective tool for you given the needs of how you want to express concepts in your business domain.
This is important because tools like Lucid are ultimately designed to allow developers, business analysts, and testers to talk about the business domain in the language of tests.
However, such tools should also be designed to avoid a common situation.
In testing, just as in development, an accretion disc of pseudo-solutions often gets bolted on to any "framework" or "process" if that framework or process does not have defined criteria for how it is supposed to operate effectively and efficiently. In other words, a process and a framework should have defined ways in which it is immediately obvious when either is being stretched beyond its current limits.
Clearly this is just the start of a project for me. I have no idea exactly where it will go in the future. What I do know is that I want to promote what I believe the future of testing is. I want to do so with my own tool solutions, using the best of what has come before me, but using that to build further based on my own experiences. I’ll have more posts going forward about how to use Lucid and, in particular, some of the rationale that I think must be in place for using tools like these.