In TDD, how can I make sure that the tests themselves do not expire (and erroneously report SUCCESS)?

In particular, this scenario bothers me:

1) I am writing a class with 1 member variable and copy function

class MyClass { private: int grade; public: void setGrade(int x) { grade = x; } int getGrade() { return grade; } void copyFrom(const MyClass* src) { grade = src->grade; } } 

2) Write unit test along these lines

 void testCopyFrom() { MyClass mc1; MyClass mc2; mc1.setGrade(-347); mc2.setGrade(10); mc2.copyFrom(&mc1); TS_ASSERT_EQUALS(mc2.getGrade(), -347); } 

3) After a couple of months I add a second member variable

 private: int grade, extra; 

and (you guessed it!) forget to update the copyFrom () function accordingly.

In this case, unit test will erroneously report success . Did I do something with the test design?

+4
source share
2 answers

TDD means a test first : you must update your code before changing the code. In this case, if you decide to add extra , you should add tests for the API around extra (until you have them, but maybe you want getExtra() , etc.), and then, as you add and revise the tests, you notice that you need to add calls to setExtra() and getExtra() to testCopyFrom() .

At this point, your tests will in most cases fail ( red ), and then you can make real code to pass them ( green ), and finally clear up and refactor , using your tests as a guide on what you broke something.

More about red-green-refactor is TDD.

In addition, you should mark getGrade() as const , i.e.

 int getGrade() const { return grade; } 

This means that you can use the const pointer or a reference to an instance of MyClass to get an estimate.

+5
source

In this particular case, the test is not incorrect - it does (and reports) exactly what you configured it. A unit test does not care about the implementation of the goal - anyway, you added the second property.

Whatever you choose, write another test that checks the new property after the copy. Testing copyFrom really tells you that the copyFrom operation was successful when it was called - it does not give any guarantees regarding the volume of the copy operation, because for this you need to conduct separate tests.

Another way to look at it: just because you called the function, and it returned without throwing an exception, this in itself is not a sign of success or failure - it simply returns to the caller. You need to either modify copyFrom to return a success / failure indication (or throw an exception on failure), or you need to examine the target environment more to determine success or failure.

0
source

Source: https://habr.com/ru/post/1413081/


All Articles