Automated Unit Tests in my life – Part 3
Part 3. Work or play?
The World before
Let’s think about our working cycle. I am not sure about you but… here how my working style looked before:
1) Wrote the code, which is a solution for requirements
2) Wrote a tester (Exe, or GUI)
3) Checked that it works. Mostly I checked expectations visually: using debugger or printing the results to a file (Text or XML) and looking at the file.
Let’s see which problems could appeared:
You write code to solute some requirement. Then you check it. Sometimes you have to write more code, which breaks your old test, so you write a new test. This is the reason that you will want first to finish writing all the code and then to write tests at the end. And I will tell you from experience – this is bad, really bad! Coding like this is problematic: the code becomes bombastic – it will take you more thinking and time to write it, you should remember many details, if you went out in the middle, takes long time to remember all the details, and this is the reason we write some not needed, I call it not “clean” code.
2) Tests run took a long time because I had to look at each test result visually and it took lot of time (sometimes had to look at big files). Of course we don’t want to run “old” tests when new are added.
3) Mostly sometimes we forget to write all tests, especially when the code is done after tests are written. Even if we write tests, we not always run all of them because it takes long time – to run each test and look visually at all tests results.
There are also situations when unit tests were not made. In order to save time people made integration tests, or in better case “unit tests” that check number of dependent components together. It never ends well, I can tell.
When you work test driven it’s all different… What is different ?
Work is a game
After few weeks of using automated unit tests and test driven, I made my “own” system of writing a code.
And the work became to look like a game. Here are the rules of the game:
1) Write down requirements logic – all detailed requirements (on paper or document)
· Try to write a question for each requirement in the code – this will be the name of your test function.
· Run current test. Of course the test will fail – sure there is no code yet.
· Now write a minimal code in order to pass the test.
· Run current test and make it pass (by adding required code and etc). Test passes when expected result equals to test result.
· Write the different expectations for current function, so copy – paste same code, just change input and expected result values. Think when your specific test can fail. So each requirement will have different test for different situation
Now add new function (or logic) test. Each time when you add a new test – run all tests. This will show you that if you have added some new logic you did not break old one. Sometimes when we add a new logic we break old one. When new requirements are implemented, logic is changed, so expected result is affected and an assertion Assert.AreEqual(actual, expected); fails.
After practicing this I found in internet a nice diagram that shows similar flow.
They call it Test Driven Development. And here is a TDD (Test Driven Development) cycle:
I hope we are agreed that this is a big change in coding cycle. A different way of thinking and different way of writing the code. It is not so easy to change the way of thinking when we are used to other things. And it was not as easy for me at the beginning.
But in our life we always learn something new, change things, our tastes change.
We become better, our code quality becomes higher – I call it self-development or evolution.