You are here

You are here

Cucumber: Good for more than just behavior-driven development testing

Michael Fritzius President, Arch DevOps, LLC

People tend to think that certain developer tools should be used in a prescribed way, and they construct rules along those lines. But some incredible breakthroughs happen when you start to bend,—or even break—the rules.

Take Cucumber, which combines readability with executable test code. Some say it should be used only for testing software created with a behavior-driven development (BDD) methodology. But that's not true, and there are some creative and unconventional ways to break that rule. 

What Cucumber actually does

Although people often use Cucumber in testing, its actual purpose is to decide what code should be executed, based on the phrasing found in a Feature file. Let that sink in. Aslak Hellesøy, inventor of Cucumber, did more than just provide a great way to execute tests. He has, perhaps accidentally, given the world an insanely versatile English-to-whatever converter. With that comes several superpowers, including the following.

Hiding the ugly

Anytime low-level "ugly" code can be abstracted away, there's less to think about (that is, until it's time to use it again). Although the code can be squirreled away in a place where it doesn't get seen often, using it can be a challenging mix of, "What class was I supposed to call?" "What order are the parameters supposed to come in?" and "Where's the code that uses that method so I don't have to type all that out again?" Cucumber's syntax can pipe directly into code that handles all of that for you, so it doesn't slow you down. 

Context lock

There's a cost to the context switching that happens when you take human-think and transform it into computer-speak. Whether it's a little or a lot, every time the question of, "How do I write code to get it to do [blank]?" that cost adds up. With Cucumber, that cost is minimized, and in some cases, eliminated entirely. Since Feature files are written in English (which is both human-think and computer-speak), with the right architecture the focus is locked on the task at hand, since there's no mental people-to-processor translation.

Prose funneling

Computer languages can be a blessing and a curse because they let you write the same code in an infinite number of ways. This flexibility means that two coders might create problematic inconsistencies by writing code in two different ways—even though it's supposed to do the same thing. With Cucumber's ability to understand regular expressions, you can call a single piece of code in a multitude of ways.

When I click on the Submit button
When I click the Submit button
When I have clicked the Submit button 
When(~/I (?:click|have clicked) (?:the|on the) Submit button$/) {
  /* do awesome things here */ 
Whether you say, "I click on the Submit button," "I click the Submit button," or "I have clicked the Submit button," the variation of prose is at the English layer, not the code layer. All those styles can be "funneled" into an agreed-upon block of code.  

Increasing reach

As computer languages and tools become more advanced, the number of people who have enough technical skill to wield them gets smaller. The more "developer-y" one must be to use a tool, the fewer people will be able to use it. Its reach becomes smaller.

Cucumber's ability to wrap a readable layer around the code increases the reach significantly. Junior- and senior-level developers, business analysts, project managers, and manual and automation testers can all make use of tools when the working-layer language is English instead of code. 

Now let's look at some real-world examples of how these newfound mutant powers can be used.

Data generation

In high-performance computing, applications often deal with raw data instead of spending cycles converting it into something pretty. But it's difficult to generate test data.

Imagine that the raw data is a chunk of hex code. New data could be generated by hand. But manual generation is both time-consuming and limited to just a few people.

So spend time writing steps in Cucumber that have the logic built in to create data for you. If you know, for example, that byte 24 controls some kind of status, you could write a step that says: 

Given I set the "Status" to "Active"... and have it set that byte for you, to whatever value means "Active." 

The approach has the advantages that it's easier to read and produce, more people can help produce it, and more people will have visibility into what data is used for testing. 

Fuzz testing

Sometimes, generating random sets of data will find issues deeper in code, but tools and code that can produce it can be cryptic. Leaning on the example above, we could have a step that looks like this: 

Given I set the "Status" to a random character
And the "Age" is set between 3 and 50
And the "Hair Color" is one of "Red, Brown, Blond, Gray"
As fuzzed data is generated, you (and others) will have a good idea about what constraints were involved during creation. You can also generate as many sets of fuzzed data as you want, by simply running the Feature again. 

System maintenance

Some tests take care of basic housekeeping: moving log files, deleting items, clearing a cache. But none of those are limited to a testing context. Many system administrators use a melange of Bash, Python, Perl, sed, awk, ssh, and many other system-level commands to accomplish these tasks.

It's a lot to keep track of, and definitely incurs a context switch. Instead of the context switch between all these different languages and utilities—and of maintaining a repository of small scripts—this can be taken care of with Cucumber. Who knows? You might even invent the next Chef, Puppet, or Docker replacement.

Database manipulation

For applications that are database-heavy, creating or modifying test data can be extremely tedious. Complex joins, data conversions, and the sheer size of some queries make manipulation slow. But Cucumber lets you enter data simply, and the underlying code takes care of interacting with the database.

I recently completed a tool for a client that does exactly that. Data is entered into a Feature file exactly as you see it on the screen, and all the data types, conversions, and inserts are handled at deeper levels of the code. I hid the ugly code so it wasn't dirtying up the working layer, freeing people up to create test data quickly and easily. 

Code generation

As market demands increase, you need to use frameworks to construct software quickly. But consider this: Code is really just text, and you can do whatever you want to it. If you have some simple methods or classes, you can combine them like Lego bricks, based on instructions found in a Feature file. Since you'll write less new code, fewer bugs should show up. Very nice. 

Misusing Cucumber for fun and profit

These are just a few examples of the benefits you get by "misusing" a single tool. There are thousands of others. Does this give you some ideas? What are some common rules you can bend where you operate? Where are some places that you can apply some lateral thinking? How else can you misuse Cucumber—and hundreds of other tools—to give you an edge that no one else has? Share your thoughts in the comments section below.

Keep learning

Read more articles about: App Dev & TestingTesting