I have a recurring question when writing unit tests for code that involves constant string values.
Let's take an example of a method/function that does some processing and returns a string containing a pre-defined constant. In python, that would be something like:
STRING_TEMPLATE = "/some/constant/string/with/%s/that/needs/interpolation/"
def process(some_param):
# We do some meaningful work that gives us a value
result = _some_meaningful_action()
return STRING_TEMPLATE % result
If I want to unit test process
, one of my tests will check the return value. This is where I wonder what the best solution is.
In my unit test, I can:
- apply DRY and use the already defined constant
- repeat myself and rewrite the entire string
def test_foo_should_return_correct_url():
string_result = process()
# Applying DRY and using the already defined constant
assert STRING_TEMPLATE % "1234" == string_result
# Repeating myself, repeating myself
assert "/some/constant/string/with/1234/that/needs/interpolation/" == url
The advantage I see in the former is that my test will break if I put the wrong string value in my constant. The inconvenient is that I may be rewriting the same string over and over again across different unit tests.
Best Answer
There's a little warning about the DRY principle that many people aren't aware of: Don't get so obsessed about avoiding repetition that you remove 'duplicates' of things that appear to be the same but are actually conceptually very different.
As an extreme example you wouldn't try to remove the repetition of the duplicates of '/s', 'th', 'on', 'nt', etc within your original string.
In your particular example, you don't/shouldn't care about implementation details of your code under test. (I.e. that it uses the
STRING_TEMPLATE
const.) Your test cares about the fact that when you:The fact that "/some/constant/string/with/1234/that/needs/interpolation/" is similar to
STRING_TEMPLATE
should be considered coincidental, not a violation of DRY.