Today I want to touch Application Lifecycle Management and want especially get you closer to Unit-Tests and put you in the direction of Test Driven Development (TDD).
What is testing about?
If you develop an application sooner or later you will come to the point where you want to write tests for it. At the latest when you just fixed a bug and realized afterwards that five other bugs came up with your “fix”.
Unit-Tests can help you out with that. With a Unit-Test you can check whether a function brings the excepted result or not. It’s only testing a small piece (unit) of your software. Getting test cases a green color is not the only reason why you should take a closer look into unit testing.
The more you test the closer you get to software with fewer bugs which should be a general goal to achieve.
Different kinds of testing
This is a very common theme so I will only pick up that in short:
Unit-Tests are only testing the smallest piece you can have. A function,a class etc. You give an input and get an output to check.
Integration-Tests are covering a bit more. They are also testing how different parts of the software react together. With this you can test whole workflows where one or more parts of the software have to work in interaction.
System-Tests are testing the whole system like your complete software or a basic challenge your software has to fulfill.
Last, the testing at the customer (maybe also made by the customer) is one of the most important tests. Here the customer can check if the software gives him the result he is expecting and that everything works well.
Advantages of testing
Testing has many advantages. Mostly you only discover them when you see the effort of testing like finding a bug faster or even not producing one because a test told you something is wrong before the check-in. But here are some points I find very important to mention:
- Most important: With testing you can ensure, that the result of your function is right. And you can ensure that it stays correct over the next versions of your software in the future. This can help you a lot while increasing the functionality of your software.
- Another huge benefit of unit testing is that developers who have to write unit tests better and deeply understand what they are really doing. If they have to test they have to understand the whole context. They have to put the arrangement in the correct place, test the important unit and analyze the results. Especially in larger projects this can be a big advantage.
- Further: If you think about testing while you are programming something, you will notice that your code-quality will improve. You are forced to write functions, methods and classes close to the Single-Responsibility-Principle which makes testing and understanding code easier. (More about Single responsibility to find here).
- Like in continuous integration (with something like TeamCity or TFS) you have a very short period of time until you get feedback of what you have done in your code. So, depending on the size of the project, running at least the tests which have touched the code you made changes to locally will bring you more safety before applying your changes to your continuous integration system. You have a feedback almost immediately.
- In case of an existing system tests can help you during refactoring to ensure that you not changed (or broke) the idea of the method or class you are refactoring. So it’s not a big deal to introduce new technologies or keeping your software up to date with the newest features if you can ensure everything works as before after the changes.
One argument against testing is that “It takes to much time”. But looking closer into this, this is not really true because: Only in the beginning you are faster while developing a software. But the time you spend finding a bug is much less WITH testing than without. So you spend more developing-time but you are faster in the end. The time you need to debug to find a bug decreases if you have unit tests which describe exactly what is failing. So it saves time. And money!
The Arrange-Act-Assert-Pattern is very common when you are going to write unit-tests. It describes the three essential steps to get feedback from what you want to test.
The Arrange-Phase gets your system ready and in position to start the tests. Variables will be declared and made ready. Mocking should be made in this phase etc. If the arrange phase is done the act-phase should be more or less only the call to your method to get you output. This output has to be validated in the third phase (Assert). Here you go along asking the question “Is my current output what I expected”. (Important: Do not go along checking manually (if/else) if something is true or false here. This is what you have Asserts for! )
Test Driven Development
The approach of testing before (test-first) or during implementing the code describes “Test Driven Development” best. This combines several advantages I mentioned before: First you have to really think “What should my class/method/function do?”
This also gets you to clarify the requirements. During writing tests more and more requirements come up which could have been unclear in the beginning. So in the end of writing your tests you have a clear understanding of what you are going to program and what it should exactly do. (Of course in the beginning every test will fail because nothing is implemented yet). Also you have some interfaces which have to be implemented by your code, because your tests will rely on that. This gives you also feedback if your design approach can be used or not. So your design is “reviewed” by the test you are writing.
After this you are going to implement your functions. With your tests your implementation will be much cleaner and easier to understand. The separation between functionalities will be more exact. Your code-quality will improve. With your implementation new functions grow up and have also to be tested. So this is going like parallel.
And last but not least: At the end of your implementation you have a correct implementation as expected (if every test passes) and everything is covered with unit-tests. It will keep its functionality as long as you don’t change the code and can for example easy be refactored if your software gets bigger.
So you have:
- No untested functions
- Clean and refactored code
- Clear design
- Exact documentation of your code
Writing Unit-Tests does not really have a disadvantage. Even the time-argument can be destroyed when you take a closer look. Unit-tests give you the feeling about creating great software and ensure the behavior that you want to achieve. With every change you can be sure that the behavior before was not affected. And unit-tests will give you a close feedback. Principles like KISS (Keep It Simple Stupid) and YAGNI (You ain’t gonna need it) are really taken into account with Test-Driven-Development. Also your design is more clear and understandable. Your developers will have a better overview of the code, a better understanding and will find bugs earlier and, if one comes up, fix them faster. This is the way to get high-quality software and save money.