Regarding "Test Contra-variance"

138 views
Skip to first unread message

Chilon Sage

unread,
Oct 4, 2017, 5:29:51 PM10/4/17
to Clean Code Discussion
Hi all,

I found last Robert Martin's blog (Test Contra-variance) quite interesting. Especially this part:

As I look at all those private method in X I will inevitably see that there are ways to group those methods into different classes. One group of methods will use a particular subset of the fields of X. That group can be extracted as
 a class.

> But you don’t write a new test for that class, do you?
No! Because every bit of the code within that new class is being covered by the tests that are still just using the public API of X.

I have found myself many times facing this dilema when extracting code to a new class. "Move" relevant unit tests to a new file or keep them in tests of the original class? I usually do the second, but what troubles me is that there are cases where I prefer the second.

For example a couple of days ago I had a class where its unit tests had become increasingly complex, because more functionality was added to the class over time.

Initially the class only calculated paths over a graph. But then we also needed to generate a unique ID for each path and manage its lifecycle (adding/removing/updating paths). As a consiquence the "addPath" test did not only need to verify that new path calculation was correct, but also that a unique ID was generated and the path was kept internally by the object (so it can be later removed or queried). Apart from unit tests suddenly becoming more complex and difficult to write, this probably was also an indication that SRP is violated.

So I decided to extract the path calculation to a separate class, so that I can offload the tests of the original class (by writing separate tests for the new class). The tests of the original class will now only care about the path
management logic and make sure that the path calcuation is delegated to the new class (no need to verify that the actual path calculation was correct).

This is in contrast to what the blog mentions, since the "structural symmetry" between the tests and the code is maintained. I wonder whether I should take another approach or we should consider extracting classes due to violation of SRP a different case from extracting classes for readability/cleanliness reasons.


Chilon Sage

unread,
Oct 4, 2017, 5:39:41 PM10/4/17
to Clean Code Discussion
I usually do the second, but what troubles me is that there are cases where I prefer the first one.

Small correction (it seems that I cannot edit the original post)

Israel Fonseca

unread,
Oct 10, 2017, 12:50:41 PM10/10/17
to Clean Code Discussion
In your example I would also extract that class and make it own tests. If I extract something (method/class) that will be reused by something else, it's strange to me if it don't build its own test suite. If tests are also documentation, it seems to me that in that sense you have a undocumented component and that "looks bad". Given the following example:

We have the ListProductsForSaleUsecase that at some point will have to do some nasty math to calculate the product price with taxes that varies depending on the user. It really seems off to me if I just extract this to a TaxCalculator and keep the tests on the ListProductForSaleUsecase. As this tax calculator probably could be useful in other scenarios like DetailProductUsecase or a SalesReportUsecase, it would be strange when a requirement for this calculation changes and now you must "guess" where is the location of the test to change.

In the end I always create another test suite when that "refactored component" is reused by something, doing otherwise sounds off, but maybe I'm also wrong. :)


Em qua, 4 de out de 2017 às 18:39, Chilon Sage <chilo...@gmail.com> escreveu:
I usually do the second, but what troubles me is that there are cases where I prefer the first one.

Small correction (it seems that I cannot edit the original post)

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at https://groups.google.com/group/clean-code-discussion.
Reply all
Reply to author
Forward
0 new messages