There are two main reasons why that may happen:
- Teamscale always takes all source lines into account, some coverage tools only count those that were loaded at runtime
- Teamscale may deem certain lines as coverable or uncoverable where your tool has a different opinion
We'll go into detail about both of these below.
Teamscale always takes all source lines into account
When we measure coverage, we not only need to know, which lines were executed during our tests, we also need to know, which lines in the system can even be executed. Then we can divide one by the other. Some coverage tools will only count source lines that were actually loaded at runtime (e.g. dotCover will only count source lines that belong to assemblies that were loaded at runtime). Thus, these tools will sometimes report much bigger test coverage values, since they ignore all lines in files that are not covered by your tests at all. This is usually not what you want. Instead, Teamscale will truthfully show these files as not being covered at all and thus have a lower test coverage value.
Teamscale may deem certain lines as coverable or uncoverable
Which lines in your source files should be counted when calculating the test coverage is a disputed topic. Almost every tool out there does it differently. It is thus likely that your test coverage tool will deem certain lines as coverable which Teamscale does not -- and vice versa. Thus, test coverage values for a single file may differ between Teamscale and your coverage tool. You can easily see which lines Teamscale thinks are coverable in the code perspective by enabling test coverage in the sidebar. Lines shown as red, green or yellow are coverable while white lines are not.
Most notably, Teamscale will never count class and method definitions as coverable while in some dynamic languages like Python, coverage tools may flag these as covered.