Fl4m3Ph03n1x
Background
I have a test suite and I need to know the coverage of the project.
I have played around with mix test --cover but I find the native erlang’s coverage analysis tool to be insufficient at best.
The native coverage tool doesn’t tell you about branch coverage nor function coverage. It’s only metric seems to be relevant lines which I have no idea how they calculate. For all I know, this is just the most basic form of test coverage: see if a given text line was executed.
What have you tried?
I have tried Coverex but the result was disastrous. Not only does it suffer from the same issues that the native tool does, it also seems not produce correct results as it counts imported modules as untested.
Or maybe it is doing a great job and my code is poorly tested, but I can’t know for sure because it doesn’t tell me how it is evaluating my code. Have 40% coverage in a file? What am I missing? I can’t know, the tool wont tell me.
I am now using ExCoveralls. It is considerably better than the previous options, it allows me to easily configure which folders I want to ignore, but it uses the native coverage tool, so it suffers pretty much from the same issues.
What do you want?
I was hoping to find something among the lines of Istanbul, or in this case nyc:
It’s test coverage analysis tells me everything I need to know, metrics and all:
Branches, Functions, Lines, Statements, everything you need to know is there.
Question
- Is there any tool that uses Istanbul for code coverage metrics with Elixir instead of the native erlang one?
- If not, is there a way to configure the native coverage tool to give me more information?
- Which metrics does the native coverage tool uses ?
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #ai
- #graphql
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex











Showing Posts 1 to 10- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
hauleth
No, as InstanbulJS is ECMAScript specific. There is no “general purpose” coverage analysis tool, as this kind of metric is highly language/platform dependant.
You can check out
covermodule to see what you can get out of it. As far as I know this is only coverage tool available.Fl4m3Ph03n1x
I already did it. This module is what I refer to as the native cover tool and all the drawbacks I present are actually drawbacks of cover - which is why I was trying to find an alternative.
So sad this is the only choice we have …
dimitarvp
Have you tried https://github.com/parroty/excoveralls?
Fl4m3Ph03n1x
…
hauleth
The point is that in Erlang there is no much difference between statements and lines, so I would roughly say that line = statement. Second stat is branch which also do not make much sense, as most of the time Erlang will use pattern match, so it will be split into 2 categories:
Both of these are available in
covermodule.Functions are available as well as modules in
cover, so that shouldn’t be much of the issue either.So as you can see that metrics either do not make sense or are supported in Erlang’s
cover.Fl4m3Ph03n1x
No. Lines are not statements.
No, branches !== pattern matching. A single
ifcan have several branches. This has nothing to do with pattern matching nor multi-clause functions.The fact that in Elixir you can have multiclause functions thanks to pattern matching and avoid long
iforcondstatements is a nice feature, but pattern matching together with guards can only take you so far and even though all multiclause functions can be converted toifcounterparts, the reverse is not possible.I recommend you dive deeper into the world of coverage metrics. Only then will you understand that they do make sense.
hauleth
Erlang do not have notation of “statement” in its’
.beamfiles, only lines are stored. While in theory you could use'Abst'chunk to extract “statements” it would be infeasible due to macros (especially in Elixir), and even then there is no mapping between'Abst'values and'Code'segments (only'Line'have such relation).So unless you write EEP to introduce such connection between “statement” and
'Code'chunk then it is not possible with current VM implementation.Yes, usually (and in Elixir always) 2.
It is possible, but not always feasible.
Any code in form of:
can be written as:
And it doesn’t matter what is
a.Fl4m3Ph03n1x
This is interesting. It appears that even though no
.beamfile is created, you are still correct !I would agree with you if only guards weren’t limited. The limitations with guards directly imply that some conditions cannot be converted into the pattern matching formula. For example,
Map.key?can’t be used in a guard. if you haveThen you are stuck.
Interesting discussion overall, can’t wait to see where it leads!
Conclusions so far:
michalmuskala
FWIW the current cover tool does not use the assembly stored in
.beamfiles. What it does is to retrieve the Erlang AST for the module, transform it and recompile.The transformation consists primarily of introducing calls to
:ets.update_counter/3each time the line annotation of the AST changes. The analysis is just counting how many lines could be called vs how many were actually called.An Elixir version that worked on Elixir AST in a similar way wouldn’t be extremely hard to do. It could also inject the counter calls for each branch, etc, to achieve the desired coverage.
hauleth
No exactly, the difference is that JS is interpreted, so it has no notion of “compiled code”. In Erlang on the other hand there is such possibility, and single line can result in multiple VM “statements”, for example:
Will result with 2 instructions:
So you can see that it is hard to match statements to instructions, especially as in theory compiler is free to reorder commands as it pleases as long as the result is the same (this can be especially seen in C/C++ where it is written in standard, and result of it is that
foo(a++, a++)is undefined behaviour).