Should unittest assertion values be hardcoded or can they be references to source code variables?
inna last edited by
Heavily simplified example that I'm trying to make language agnostic: I have an XmlView Object that has a constant property FACTORY_NAME labeled "factory" and a constant property VIEW_NAME labeled "view". There is also a twodimensional string array somewhere that contains the links between the numbers 1, 3, 4 5 and a localization variable for their string representation in English, German and French, which are in resource files somewhere.
I then have a REST API call on
, where factory is whatever FACTORY_NAME is, view is whatever VIEW_NAME is, %did is whatever number you entered as a path parameter and can be either, 1, 3, 4 or 5 as a number, and %sid is a localized representation of that number (so one, ein, un; three, drei, trois; four, vier, quatre; five, fünf, cinq). Note that the actual code is many times more complicated with hundreds of API endpoints that do far more complicated things, this is just an example.
In the above contrived example, there are essentially 3 things I want to test:
- That the
- That any id number I enter in the above endpoint is in the expected response value, and that it's in the allowed values for the id property;
- That the response XML is what I expect it to be.
There are other things to test, but these will do for this example.
Based on the above example, to what extent should this test use hardcoded values and/or iteration to test that this code returns the expected values?
- Should I write 4 separate assertions that a GET to the factory endpoint gives an expected value, with the contacted endpoint hardcoded and comparing the XML response to the string above, hardcoded in the test? This seems kinda brittle since any change will break my test and I'll have a lot of repeated code.
- Should I write 4 separate assertions as above, again with the factory endpoint hardcoded, but then using Xpath to retrieve the variable part and then comparing this to a hardcoded value?
- Should I write 4 separate assertions, but with everything that's possibly variable being retrieved from the rest of my codebase?
- Should I iterate over my localized string array and do an assert for each item in the array?
- Should I do something else?
I'm not sure what to do. Using the existing variables removes a lot of manually changing my tests when I change something, but it also means that I'm just checking if my values are processed correctly by my code and not if the values themselves are correct. Are there any generally accepted best practices for this scenario?
- That the
I don't thinks there's a good or bad here, its a tradeoff.
My own preference would be to hardcode values you assert on - Decoupling your tests from the implementation has its benefits.
i.e. do you want to change the test if the implementation changes, without the behavior changing?
If you need to change your test a lot if the implementation changes, you might be testing the wrong thing (or have a very unstable API?)