Posts Tagged testing
When I first started writing unit tests, I followed the common convention in C# for method naming:
Later, I adopted the convention of separating words with underscores:
At some point I figured the approach above makes the name of the method look like the title of an article. I then decided to go with the same approach, but making everything lower case:
In some cases, I may use uppercase if I want to draw attention to something in particular:
I like when the code is calm to look at, and it draws my attention to things as appropriate.
This is a question asked many times: What is the difference between Test-Driven Development (TDD) and Behavior-Driven Development (BDD).
In my mind, I’ve accepted the following explanation:
Doing TDD, I write the code I want to have;
Doing BDD: I describe the behavior I need to have
I use both approches together: I start writing my tests in terms of GWT (Given-When-Then), describing the behavior I need to have, and as I implement those individual steps I write the code I want to have.
This is the simplified explanation that works in my own mind, and it has taken many years for it to take that shape. It may not work to others, but I’m sticking with it for the time being, at least until I find a better way to explain it.
I sense there’ll be more posts coming up expending on this subject. 🙂
As I mentioned in my post on Test Style: AAA or GWT, I’ve deliberately started thinking of everything in terms of GWT (Given-When-Then). So, when I’m beginning to write a new test, instead of writing this:
I write this:
Regardless of the style, though, if I can’t think of what should go in each one of those sections, I may have one of two problems:
- I don’t have enough requirements, or
- I don’t understand the requirements I have
I’ve gotten into the habit of thinking this way: No GWT, no code!
The reason for that is: if I either don’t have enough requirements or don’t understand the ones I have to a point where I can’t fill out my GWT sections, then I should NOT be writing any code. Whatever code I write is very likely to be thrown away, and unless I have a lot time in my hands to be simply toying with writing code, I should refuse to write any code and go find help to have a clear idea about what I’m supposed to implement.
Many years ago, after really getting into writing tests, I fell into the same trap newcomers do: my test code was very messy! Eventually, I heard of the AAA-style of organizing test code. AAA stands for Arrange-Act-Assert. There are several posts out there that show it. Here’s a link to one, in case you don’t know what this is all about.
After years of following that format, I learned about BDD (Behavior-Driven Development), and that’s where I learned about GWT (Given-When-Then).
Several years ago, I stopped thinking about AAA when writing any kind of test and got convinced that I should always think in terms of GWT. Why? Because AAA is too technical, while GWT works well both for technical people as well as for business or QA folks. Now, why’s that important?
For me, when I want to get feedback by having my code reviewed, if I stick with the GWT mindset, I can get pretty much anybody involved with the project to help me review my code. That means I can easily work with another developer, business analyst, or QA guy.
So, when I’m about to write tests, instead of thinking how I’m going to…
- Arrange my test, I think what I’m Given…
- Act in my test, I think When something happens…
- Assert the results, I think if that something happens Then this is what I expect as the outcome.
In both styles, the structure of the test is pretty much the same. However, this shift in how I approach coding makes me think more from a business-oriented point of view, and this mindset opens up possibilities regarding the number of people I can collaborate with in order to build a better product.
When using SpecFlow’s dialog to generate step definition skeletons, the default style is “Regular expressions in attributes”:
That produces results like this:
That looks very messy to me. The regular expression text can be read easily, but then the PascalCase method underneath looks like it is too much. I see redudant code. I see dead code. 🙂
I personally like the “Method name – underscores” style better:
That looks a lot cleaner to me. Yes, I am a little biased after having spent several years in Ruby-land, but hey, I had adopted this style in C# before that. While this is not a common format for method names in C#, I don’t really care, as nobody should be calling this methods in the common way anyway, so I rather follow a style that makes the code read better, without junk around that doesn’t add anything to my understanding of the code.
Note: by the way, I do rename those p0 and P0 references!!
At the last Virtual Brown Bag we talked about Test-Driven Development (TDD), Behavior-Driven Development (BDD), and related subjects (you can watch it here).
I’ve been very fortunate in the last 5 years working on projects where I simply write the tests as part of the work. It’s just something I do.
Is it a new feature?
If I need to work on a new feature, I write the tests to spec out my understanding of the feature. If I can’t write the test, most likely I don’t understand what the feature is, and if that’s the case, I shouldn’t write any code to begin with. Instead, I should pair up with the QA guys and/or the business analysts (or work directly with my client), and make sure I understand not only what the feature is, but also why it is important to the business.
Is it a defect?
If I need to work on fixing a defect, I’ll do my best to write a test that reproduces the issue. Granted, some issues (such as multi-threading issues) are really difficult to reproduce in test, but hopefully those types of issues aren’t the core of my projects. Whenever there is an area that’s hard to test, I’ll try to isolate as much of the code as possible, decreasing the surface that’s hard to be tested.
The biggest lessons I’ve learned from testing
While I think I’ve learned quite a bit about the technical aspects of writing tests, and have been harvesting so many positive outcomes, such as writing better code, I don’t think that alone makes me a better developer.
I believe that the act of taking a step back to think about how I’m going to write tests has made me take an extra step back to understand what it is that I’m building. This has made me collaborate a lot more with people who actually understand the business. I don’t really care much anymore about using this or that framework/language/etc just because it’s cool; I care much more about building features that will bring value to my client. Seeing a client smile because you gave him or her the feature needed is very rewarding.
A recent experience
In the last 3 months I’ve been working part time on a project where I’m the only developer, and I have no QA, no business analyst, no project manager. Here are some bullets from my personal project notes:
- The first phase of this project has gone into production two weeks ago
- The client is beyond happy
- Very few defects were found in production (and corrected immediately)
- There are close to 400 tests
- I do NOT have everything under test. I’m keeping Controllers very thin, calling out to Commands, Services, etc. Things the controllers call ARE under test.
The whole testing thing…
As I finished writing this post, I just remember I actually wrote another post about the whole testing thing 8 years ago! Time sure flies by…
Three years ago I blogged about my thoughts at time on the whole testing thing. I have stuck with the practices and really believe on it. I’ve tried different tools and approaches, and I keep trying different things as I go. Behavior-Driven Development (BDD) seemed like my next step, but it didn’t take me long to realize MS-Test didn’t give me what I needed in order to start to get into that practice. There wasn’t much I could do as I was stuck with it.
When C# 3.0 came out, I’ve learned how I could improve my tests using extension methods, building some sort of fluent DSL to test certain things. Eventually, I was able to migrate to xUnit, along with SubSpec, and then I was able to write tests a lot better, following the “given-when-then” style. Writing new features and certain components following that style has been great; I believe everything I wrote following that approach has a much better design and quality.
I had heard Rails developers gave a lot more importance to BDD and testability than .NET developers, so that was one of the driving factors that encouraged me to try Rails.
After getting a little more comfortable with Rails and Ruby, I started to devote more time to RSpec and Cucumber, without really understanding much what they were exactly. So far, I’m enjoying using both. I’m almost done reading the RSpec book (I’ll post a quick review once I’m done) and writing as many tests as I can, but I still have lots to learn; I’m still at that stage where I do know there must be a better way to write something, but I’m not to a point where I know how to do it.
I am writing lots of “features” formatted so that I can drop them into Cucumber .feature files, and then implementing them. I’m finally realizing some benefits of BDD that were apparent to me before. Up until recently, I was seeing BDD mostly as a way to write tests where the scenarios were described such as “given whatever, when something happens, then I should get x”. But those were described as strings surrounded by C# code, so the business value wasn’t immediately apparent.
Now, however, I’ve been sticking to this format (right off the official Cucumber site):
This format makes it a lot easier to see the business value out of an atomic feature. It shows a short title for the feature, the ultimate value out of it (“in order to…”), who’s getting benefit from it (“as a…”), and what the person wants (“I want to…”). Then, it describes the different scenarios that exist for the given feature. I like the fact that there’s no specific programming language clutter mixed in with the description of the feature.
If I’m the one writing those stories, as a developer, it forces me to be as clear and succinct with the English language as possible, so that it will make it easier for me to validate these with my clients and users; and as they get familiar with the format, they can start providing me the stories themselves.
Another advantage I’ve been noticing doing these is that by analyzing the number of steps within a given scenario I can identify whether the user experience is going to be good or not. The scenario unveils how hard it is for the user to access the feature (“user has to click this, select that, fill out the other, click this other thing, and only then get to what she needs…”), and how the user interacts with the system (what the user does, and how the application responds).
Breaking scenarios into small, concise units… doesn’t that sound similar to “breaking classes into smaller, concise classes, methods, etc.”? Putting some good thought into writing these stories can help out the developer later when actually implementing the feature.
And here’s another benefit of keeping scenarios small and concise: planning. When discussing the feature with the clients, I can get them a feel for the complexity on each scenario, and they can tell me which scenarios are must-to-have, and which ones could come at a later time. This way we can plan on which features and which specific scenarios are going to be implemented on a given iteration or release.
I’m also following the idea that “Cucumber tests cover the application’s behavior, and RSpec tests cover class’ behavior”. In other words, I write Cucumber tests to check a feature end-to-end, from the user’s point of view, and I use RSpec to test a class’ behavior.
Some people say one of the main advantages of Cucumber is that non-technical people can easily read, or even write, the tests, but some developers say “the non-technical people will never read anything anyways, so why bother?”. So far, I’m seeing the Cucumber tests as being very beneficial for myself, for the reasons listed above (like forcing me to think of the features in a cleaner and more concise way, etc.).
At the moment, I have the following workflow:
- Write the features and store it in Evernote (tagging everything so I can group features based on specific user roles and things like that);
- Review stories with the client, rewrite pieces, split features up, move scenarios around, etc;
- Once it feels like a given feature is a little more stable, I put it on the Kanban board in AgileZen;
- Pick features that are on the board, and plan them accordingly;
- Once I start working on a given feature, it’s just a matter of turning them into a Cucumber file, and go about implementing it.
This is not written in stone, and it’s just something I’m trying out. I have no idea whether that’d scale for large teams or whatever, but I’m being pragmatic and doing whatever it takes to be productive given what I have. It seems to be working. I’ll keep you posted.