Code reusability in unit tests?
Asked Answered
L

2

7

I keep hearing people say about how tests should be simple, maintainable, straightforward, but what happens with code re-usability in unit testing?

Let's take for example:

def test_some_1():
    ...some code

def test_some_2():
    ...code repeated from test_some_1

Wouldn't it be best to encapsulate the repeated code from the two tests in a function which holds the necessary assertions?

I have argued with some programmers about this and they disagree, they said that tests should be dumb, that code re-usability is not good here. The reason for this is because it is not very clear in the django console where the assertion actually failed, because the assertion was in the function, although I disagree because using it with nose would give you the name of the test and the traceback, although the guys disagreed again, stating that a test could be invoked individually without nose (and therefore you couldn't see all those details).

What do you guys think?

  • Is it good to use code re-usability in unit tests?
  • If re-usability can/must be used then how to overcome the other problem regarding pin-pointing the assertions?
Latten answered 4/6, 2014 at 7:35 Comment(2)
do you know about the setUp and tearDown? docs.python.org/2/library/unittest.html#unittest.TestCase.setUpSeptuagint
I do know but I don't think they are relevant here. I was talking about code reusability. Check @otus's answer.Latten
K
7

The most important factors for code quality, like clarity and readability, are also important for test code. If code repetition makes it easier to read, you should do that regardless of whether it's test code you are writing, and vice versa.

For example, in one package I wrote, I had a function:

def _test_vector(self, a, b, c):
    # test the function with parameter values a, b, c
    # several asserts here to verify output of function tested

That allowed be to write all the test vectors like:

def test_vector1(self):
    self._test_vector(a=42, b=5, c="blah)

That, IMO, improves clarity, because the individual tests only include the information specific to that test.

Pinpointing assertions should always be easy. Even unittest will give you a traceback, and if your testing setup doesn't point to a particular assert you'll have a hard time debugging any test failures and should definitely switch to something sensible.

Kinsey answered 4/6, 2014 at 7:44 Comment(1)
Here I found a slightly different take away that I agreed with, and you might want to consider as well: osherove.com/blog/2007/9/22/…Shantung
N
0

As your peers said, you should write your tests dumb. There are several reasons for this, the most important one is that you want to avoid complex logic in the tests. If you do write your tests "smart" they tend to contain the same or similar logic as the code your are trying to test. This means you risk making the same mistake in both places and will miss bugs that you want to find.

Another reason is that you want your test to act as documentation of the code you are trying to test. If the test has a complex execution path through lots of functions and logic, it will not be as easy to understand. In the best of worlds you would see how the production code is intended to work just by having a glance at the test.

Nally answered 4/6, 2014 at 7:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.