I got 2 functions I want to test in my class - get
& set
. Those 2 functions do actual logic and not just return and set, so I would like to test them.
I have started to write unit tests for those functions, in pseudo code something like this:
value_to_write = 5
my_class.set_value(value_to_write)
read_value = my_class.get_value()
assert(read_value == value_to_write)
So in this example we set
and then check with get
that the set
was successful.
But then I remembered the best practice that says "Test should check one and only thing". In this example I check set
and get
together.
What is the best practice for this example?
Is creating 3 functions of checking the set
, checking the get
and finally checking that the value written with the set
is correct (like the example above)?
The problem with this method is that the third test already covers the first and second one, so I wonder what is the point
CodePudding user response:
If your class implements equals()
(or whatever the appropriate thing is in your language/platform) and another way of setting the value (i.e. via the constructor) you could set the value and then compare the whole object with a reference object that used the other way of setting the value. If this is not possible in your case, be pragmatic and use the getter anyway. After all, you will probably run into the same problem, when testing the getter (how to set the value, without using the setter).
CodePudding user response:
First of all, you should reassess whether your setters and getters should really be named as they are. While, for example, a simple validation in a setter should be fine, having setters and getters comprising much or complex logic look dodgy to me. Callers have a certain expection based on the name of a function and will not be aware that such a function does (much) more than just setting or returning a value. For example, I expect an invocation of a getter to be cheap, which will not be the case if it accesses the database instead of returning a class variable. Therefore, you could consider renaming the functions to loadX()
, getConvertedX()
, getXAsNumber
, or similar, depending on what they actually do.
To be able to detect a fault, a test oracle must be able to observe the incorrect part of the state or output. Therefore, you could consider adding a real getter, which just returns the value or reveals the internal state. This getter can have the minimal visibility that is necessary for the test to access the value. Then you could test your special setter by invoking it and verifying the outcome using the real getter. To test your special getter, you could prepare the object (if necessary, using the setter), verify whether you have the state you would like to have using the real getter, and then invoke your special getter. Alternatively, you could introduce an additional variant of your special getter that does the logic and takes the necessary input by the parameters; then, you could test that function and the original special getter would just delegate to the new function.
To sum up, I would suggest to
- assess whether the function names are appropriate
- introduce additional getters where sensible and use these to get insights about the object