Fl4m3Ph03n1x

Fl4m3Ph03n1x

Code coverage tools for Elixir?

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

  1. Is there any tool that uses Istanbul for code coverage metrics with Elixir instead of the native erlang one?
  2. If not, is there a way to configure the native coverage tool to give me more information?
  3. Which metrics does the native coverage tool uses ?

Marked As Solved

hauleth

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:

Integer.to_string(a + 1)

Will result with 2 instructions:

    {line,[{location,"lib/tasks.ex",6}]}.
    {gc_bif,'+',{f,0},1,[{x,0},{integer,1}],{x,0}}.
    {line,[{location,"lib/tasks.ex",6}]}.
    {call_ext_only,1,{extfunc,erlang,integer_to_binary,1}}.

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).

Also Liked

cblavier

cblavier

Just a brief update, because I needed to get solid code coverage for a decent phoenix app (umbrella app of 5 sub-apps, 17k loc).

On the app side, we’ve been using excoveralls : it is reliable, can be run in umbrella apps, with partitioned parallel testing and can output in different formats. :ok_hand:

Then we needed also a good UI to be able to drill down within our application code to know what to test to improve our code coverage. I tested:

  • coveralls.io: the UI is only OK but not really convenient nor pretty. I could not make Github Status checks or comments to work (in order to get instant code coverage feedback when opening a pull request). Integration in the CI was not really convenient as well because we had to disable partitioned testing to run all tests at once and upload a single report.

  • codeclimate.com was disapointing :frowning_face: Integration within CI was ok : we had to generate multiple json reports (one per partition) with excoveralls then format them, merge them and upload the whole with cc_test_reporter (binary provided by code_climate). Github feedback is working well, but you can’t really explore your code source tree within codeclimate UI. No go :no_good_man:

  • codecov.io is our choice. Integration within the CI is really simple : you can upload multiple report for a single build (one per test partition) and everything will be merged on the serverside. Github feedback is really insightful and the UI gives you the ability to drill down as you want to build your test coverage strategy :medal_sports:

Codecov sunburst GIF here

cblavier

cblavier

Hey there, I just wrote this article:

hauleth

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:

  • function clauses
  • lines

Both of these are available in cover module.

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.

dimitarvp

dimitarvp

I have badly misread while I was on the phone. Apologies.

dimitarvp

dimitarvp

Where Next?

Popular in Questions Top

belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New

We're in Beta

About us Mission Statement