Within this blog post, I would like to show how fluent style tests can simplify and speed up test creation, increase code reuse, and improves readability.
After reading this article, you will:
1. Understand what fluent style testing is about.
2. Learn the basic principles of Behavior-Driven Development.
Let’s get started.
A Good test starts with a good test case.
Writing a good test case is somewhat similar to writing a navigation plan. How do you get from point A to point B? Your plan might be traveling from point A, the North of the city to the South. Or perhaps require a much bigger plan, including several stops on the way.
A high-level plan might look like the following;
Jump in your car, drive a couple of kilometers, and you arrive.
And here an example of a detailed low-level plan;
I have my keys in my pocket, and I need to pull out my keys, insert the key into the lock, unlock the door, pull the door handle, get into the seat, fasten the seatbelt….
As you can see, this plan is far too detailed, spending too much time on the “how”. A navigation plan or a good test case, should focus on waypoints. You’re going from point A to point B to reach your destination at point C, going from one major point to another major point in your software application.
Common problems with test coding styles.
Before we go into the details of what this looks like in practice, I would like to cover common problems regarding test coding styles.
- Little to no coding style consistency (no standards/structure)
- Difficult to read and understand (procedural focus)
- Hard to maintain (test scenarios are often duplicated)
- Impossible to reuse (no discoverability, code not shareable)
Let’s go over some examples.
We have arrived at the destination, but we not sure how. You can see what will be tested; however, we don’t know how we got there.
Here an example of a detailed low-level plan. This is what we see quite often, a large complex test containing too many irrelevant details. This example is still tiny and already takes some time to understand fully.
Fluent style coding is here to help.
To solve our problem, we need to find a structure that will help us writing better test scenarios; Spending less time looking at a detailed setup; however, still be able to see how we get from point to point. This is where Behavior-driven development and fluent style coding comes into play.
We start with identifying requirements while following the behavior-driven development template is included below.
- Given some initial context (preparation)
- When an event occurs (execution)
- Then ensure some outcomes (assertion)
Now that we have a template, we can apply object-oriented principles to organize our test preparation and assertions. We will be using the Method chaining.
Method chaining, a key element of the fluent pattern, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.
In case you’re familiar with LINQ, you’ll be familiar with this concept. For example:
The code block below contains a rewritten version of the second example. You can see its path having major waypoints. The code is simpler and easier to read; scenarios are easier to reuse because they are just extension methods, and because of this, easier to maintain.
In the second part of this post, I’ll cover how to how to create fluent style tests in C# step by step, share best practices, libraries, and other helpful resources.