79616239

Date: 2025-05-11 06:53:35
Score: 1.5
Natty:
Report link

Below I am answering my own question. There is a possibility that the answer is not correct. So, I request you to point out any errors or inadequacies.

I am still unable to read the binary file and I could not locate the py2lcov so that I could try to try out the idea given by @Henry. However answer to my primary question, I have been able to figure out. Two passes of trace command were enough.

While running the module(s) with trace command <SomeFile>.cover files will be produced. This will be the original code that gets executed. The beginning of each line has a number associated (which tells the number of invocations of that line). An empty or ">>>>>>" at the beginning shows that that line did not get called. You can write a simple parser program to produce a detailed coverage output and write it to an html or xml to produce 'coverage' module like output (or you can customise it to your needs). The ">>>>>>" is produced if "--missing" option is passed in both the steps otherwise a blank is produced for the lines not covered by the unittest.

In both the passes, if you don't include the "--ignore-dir" or "--ignore-module", all the core python modules that get called while executing your actual python file (TempDelete.py in the above example). Thus for example the python is located as "/usr/lib/python3.12" then passing "/usr/lib" will suppress producing the coverage of those files. For details see the official docs.

I am writing below the contents of the test_foo.py and the two commands/passes that I had to execute.

## Contents of test_foo.py
import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

    def not_covered(self):
        print("This will never be printed.")

loader = unittest.TestLoader()
tests = loader.discover('.')
testRunner = unittest.runner.TextTestRunner()
testRunner.run(tests)

Pass 1

$ python3.12 -m trace --count --file ./coverage/coverage --ignore-dir=/usr/lib --missing -C ./coverage/ ./test_foo.py

The first pass printed the output as below, as expected

...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK
Skipping counts file './coverage/coverage': [Errno 2] No such file or directory: './coverage/coverage'

Pass 2

$ python3.12 -m trace --report --file ./coverage/coverage --ignore-dir=/usr/lib --missing --summary -C ./coverage/ ./test_foo.py

The second pass gave me the summary I was looking for.

lines   cov%   module   (path)
   18    94%   test_foo   (/home/somefolder/test_foo.py)

I am also pasting the test_foo**.cover** file to show how a .cover file looks like.

    1: import unittest
       
    2: class TestStringMethods(unittest.TestCase):
       
    1:     def test_upper(self):
    2:         self.assertEqual('foo'.upper(), 'FOO')
       
    1:     def test_isupper(self):
    2:         self.assertTrue('FOO'.isupper())
    2:         self.assertFalse('Foo'.isupper())
       
    1:     def test_split(self):
    2:         s = 'hello world'
    2:         self.assertEqual(s.split(), ['hello', 'world'])
               # check that s.split fails when the separator is not a string
    4:         with self.assertRaises(TypeError):
    2:             s.split(2)
       
    1:     def not_covered(self):
>>>>>>         print("This will never be printed.")
       
    1: loader = unittest.TestLoader()
    1: tests = loader.discover('.')
    1: testRunner = unittest.runner.TextTestRunner()
    1: testRunner.run(tests)

I think my main query is resolved but I still do not know how to read/decode the binary file. May be we are not meant to. We can however print the contents with binascii module using ascii.b2a_uu as below.

import binascii
with open("coverage/coverage", "rb") as file_handle:
    while(read_content:=file_handle.read(45)):
        binascii.b2a_uu(read_content)

It produces the output as below.

b'M*\'UQ "@H6 T    N+W1E<W1?9F]O+G!Y<0%+ 71Q DL!*&@!2P-T<0-+ BAH\n'
b'M 4L%=\'$$2P$H: %+"\'1Q!4L!*&@!2PQT<09+ 2AH 4L3=\'$\'2P$H: %+%G1Q\n'
b'M"$L!*&@!2Q=T<0E+ 2A8+0   "]H;VUE+W!A<G1I8VQE+T1E<VMT;W O5&5M\n'
b'M<$1E;&5T92]T97-T7V9O;RYP>7$*2P%T<0M+ 2AH"DL#=\'$,2P(H: I+!71Q\n'
b'M#4L!*&@*2PAT<0Y+ 2AH"DL,=\'$/2P$H: I+$W1Q$$L!*&@*2Q9T<1%+ 2AH\n'
b'M"DL7=\'$22P$H: I+&\'1Q$TL!*&@*2QET<11+ 2AH"DL)=\'$52P(H: I+"G1Q\n'
b'M%DL"*&@*2PUT<1=+ BAH"DL.=\'$82P(H: I+$\'1Q&4L$*&@*2Q%T<1I+ BAH\n'
b'G"DL&=\'$;2P(H: %+&\'1Q\'$L!*&@!2QET<1U+ 75]<1Y]<1]T<2 N\n

However I still do not know how to decode it. If you happen to know the trick, please share.

Reasons:
  • RegEx Blacklisted phrase (2.5): please share
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Henry
  • Self-answer (0.5):
  • High reputation (-1):
Posted by: Amit