pythonc#python.net

How to collect C# code coverage by running tests in Python?


I want to implement an algorithm in C# but test it in Python using python.net & pytest which I'm familiar with (and I also have a reference implementation in Python with which I want to compare outputs), so the question is: is there a way to compile C# to a DLL, import it in Python with python.net, run tests in Python and collect coverage of C# code being invoked during this process?

For example let's consider I have myclass.cs file

namespace mynamespace
{
    public class MyClass
    {
        public static int mymethod(int x, int y)
        {
            return x + y;
        }
    }
}

after that I compile it with mcs

> mcs -t:library myclass.cs

getting myclass.dll which I import using python.net library in a binding.py

from pathlib import Path

import pythonnet

pythonnet.load()
from System import Reflection

Reflection.Assembly.LoadFile(str(Path(__file__).parent / 'myclass.dll'))
import mynamespace

mymethod = mynamespace.MyClass.mymethod

after that in my test.py

from binding import mymethod


def test_mymethod():
    assert mymethod(1, 2) == 3

After running

> pytest test.py

I'm getting expected

...
test.py .                                                                                                                                                  [100%]

======================================================================= 1 passed in 0.41s ========================================================================

so far so good, but the question is how to get the coverage of original myclass.cs file? Is it even possible?


Solution

  • After searching I finally found a great dotnet-coverage tool which can be installed with

    > dotnet tool install --global dotnet-coverage
    

    and after that we can run Python tests with pytest (which call compiled C# code using python.net) and collect resulting coverage of C# project as easy as

    > dotnet coverage collect pytest --output-format cobertura --output-format coverage.xml
    

    which I can then for example upload to codecov service.