Assuming most of the classes in the code base shou...
# getting-started
i
Assuming most of the classes in the code base should be tested (besides few exceptions) what is your way to ensure that every class has equivalent test class present in the code base?
l
Coverage checks? i’m not up on coverage checks for Kotlin but we use JaCoCo for java.
i
At this point I had binary check - exists/does-not-exist, so I has something more generic in mind perhaps usage of
detekt
or
ArchUnit
l
You can have kover record coverage, and configure verify to ensure that your required code coverage is met.
👍 2
m
what is your way to ensure that every class has equivalent test class present in the code base
why that, in a first place? there shouldn’t be 1:1 between code and test classes/modules/components
l
yeah, i’d argue that having actual thresholds set for coverage is more valuable than ‘does SplineReticulator.kt have a corresponding SplineReticulatorTest.kt?’ (regardless of whether SplineReticulatorTest.kt actually tests anything useful) - again idk about Kover but for JaCoCo you can set coverage thresholds not only for statement coverage but class and branch too.
l
Kover currently supports Line, Counter, and Branch requirements (can set requirements as percentage, missed lines, covered lines, etc), and the HTML report shows class coverage, but for some reason, you can’t yet set a class coverage requirement (aside from setting coverage target to per-class and requirement to covered lines > 0).
m
and imagine scenario where you have a class and test class for it. than you end up adding more to it and you see that you can extract 2 or 3 classes out of that one. you shouldn’t create additional test classes and move related tests into those you keep 3 classes and one test class
l
I can see trying to map code file -> test file being useful for navigation (I try to do this as much as possible), but the IDE should be able to find usages of a method in tests anyways. Not sure requiring it through some static check is best, though, since it adds coupling between code and tests.
i
There are certain classes that should always be tested such as
UseCases
and
Repositories
, so I would like to simply enforce these tests by heaving some kind of linter (so tests are not forgotten when adding new class).
l
I would configure code coverage requirements for that. If you forget tests, the verify check fails.
👍 1
If you use kover (supports multiplatform projects, but only runs tests via java right now), you can set up a rule with class filter ‘*Repository’, target of class, and bound CounterType.LINE and ValueType.COVERED_PERCENTAGE minValue to your required percentage, then add other rules as needed. I’m less familiar with JaCoCo, but I believe it has a similar feature.
If you just do a lint, you can miss a method or branch in your tests. By running coverage, you can know what is/isn’t covered.
p
I think the true answer to your question is the one you’ll like the least
what is your way to ensure that every class has equivalent test class present in the code base?
It’s a human problem, not a machine problem. Just because there are files, or tests within those files or even coverage numbers, doesn’t ensure that the tests have any value. I’ve seen “tests” where someone used reflection to programmatically hit methods in classes with no actual assertions just to get “coverage”. It’s a people thing - build a culture of quality where you hold each other accountable for writing better test code. Refactor both production and test code to make it better. Changing the hearts and minds of developers to take pride in the quality will pay dividends over a brittle automated traffic cop 🙂
💯 3
l
I agree. Code coverage isn’t enough. Another team at my work started a new project with the promise of 100% code coverage, saying it will prevent major bugs, then confidently released the first version assuming green CI means no bugs… just to get a bunch of bug reports very quick. They now have strict value requirements for each test and have removed the 100% code coverage constraint in places where there’s more value elsewhere.
i
I have decided to write a custom
ArchUnit
condition and I am curious how this will evolve with project growth. Here is the code: https://github.com/TNG/ArchUnit/issues/1072#issuecomment-1454783647
m
interesting. I think it will be more pain than it’s worth but interesting code nonetheless