The single-responsibility principle is one of the fundamental principles of object orientated design. It is the idea that any object, method, variable etc has one purpose and one purpose only.
'Yes', I hear you say, 'I'm a super-duper expert in object-orientated design. I follow this principle and I defy you to find a single part of my code where I haven't followed SRP!'
Well, dear reader, how are your tests?
In my opinion, the SRP should apply to tests as well, meaning that every test should have a point, and one point only. Here is a little example showing a common way to structure tests:
Here is a little MessageListener.java class. When the a message is received, the onMessage method is called and the messageListener both stores the message and increments a counter of the total number of messages received.
All is beautiful so far.
However here is our MessageListenerTest.java:
What on earth is going on here? This test is not adhering to the SRP as it is clearly testing multiple things. There are 6 asserts in one test, which should set off alarm bells. If the messageCount is broken in the message listener, or the message isn't added to the receivedMessages collection etc, then this test will fail and the developer will have to waste time figuring out exactly what went on. Okay, in this example it's not exactly difficult to understand what is happening, but in more complicated examples this problem quickly becomes apparent.
How about writing the test like this:
Every test method has one distinct purpose which is summed up in the method name. If a test fails, you can immediately understand what has failed and which part of the code is incorrect.
So, things to look out for in your own code:
- a test method with some code, then asserts, then more code, then more asserts.
- if you break one tiny bit of your application, how many tests fail? If we change one tiny bit and suddenly 20 tests break all over the shop then what is going on?