At the beginning stages of practicing TDD, I write mostly end to end tests. I’ve seen programmers write tests to confirm ORM add method is adding data, serializer package serializing method works properly etc. To practice TDD, it is important to know what to test and what not.
- On the first post of this TDD series, repetition of a very short development cycle has been briefed
- The second post is about common misconceptions
- The third post is about test classifications
- This is the fourth one
- And the last one should be about some design patterns and tools to write maintainable tests
Table of Contents
Part 3: What to test
My first few TDD projects probably resulted in the worse design and took longer to complete as I was learning. This is why you shouldn’t jump into using TDD on a large critical project. And TDD is an art to designing your code, not to design/architect system, this ensures an agile, easy-to-change, loosely coupled code base. In TDD every line of code must be justified by a failing test written before the code. Now you know what to test – Every Line of production code. Write tests for
- Happy path – Common cases of everything
- Unhappy path – Edge cases
- To cover a bug before fixing it
- Only Public or Internal classes and routines
Definitely, I write more unit tests for my business class library as all the business logic stays here. Most of the tests are asserting states. Whenever two or more components communicate with each other, I write some integration tests or interactive assertion based test.
If you are a web developer, you may write tests for server side or client side code and use some automated test for the UI.
Whenever I have any requirement to implement any new feature, I start with simples happy path Acceptance test. This forced me to think about how the system will be used, what are the inputs and outputs, what are the dependencies, and how easy it is to use. Moreover, you write tests for everything, test drive to
- Create components (class), routines (method/function), attributes (property)
- Handling errors (throw exceptions)
- Hierarchy (Is instance of / Is assignable from)
Focus on a single unit when writing unit tests, use test doubles for other units. Design your code in such a way that you can easily achieved that.
Writing all about what to test is out of the scope of this post. If you know what not to test, then you may easily write tests for rest of the things
What not to test
I know for many programmers believe that “what stored in the database” is the most important thing in the system and these are the most important tests. Once, I have found that a test code base was build in a way so that each machine will have a newly created database on a single dedicated server. And developers are taking the opportunity to write most of their tests to assert values on original tables. That end up very badly as most of the tests have to be rewritten. The connection pool was exceeding very frequently, test base was really slow.
However, if you are using any continuous testing tools such as NCrunch, dot cover or Live Unit test make sure long-running tests are excluded from these tools. Moreover, I would recommend avoiding tests that take longer than 2 seconds. Never write tests that require to run in order.
No need to write tests for testing
- Database constraints
- Configuration
- Field values
- Static Classes
- System Classes
- Private/Protected
- Extension methods
- Third-party libraries (i.e. ORM)
- Framework
For example, if you want to use identityserver4 to build a single sign-on system. You do not need to test after configuring correctly identitiyServer4 authorize as expected. You can write this test to understand IdentityServer4 but please do not leave those test in your code base. It’s not your duty to make sure the library is working properly. Dominick Baier and Brock Allen have already tested this library.
When I love to ignore TDD
- Spiking
- Building prototype
- Experimenting
- Learning new tech
Conclusion
What to test is simply what you’re trying to implement rather than how you mean to implement it. If you don’t even know what you’re trying to accomplish, then maybe you should stop writing code and go figure that out first
Telastyn Stackexchange
Write test that is fast and asserts only one thing or one concept. Use test doubles when necessary. Do not write tests that easy to break. Do not write slow running tests. If I miss any points regarding what not to test
please add in the comments below
Next up, I will write about how to write maintainable test base that makes TDD more pleasurable
Very resourceful and lots of materials are referred for self study.
Thanks for your feedback