Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Python's unittest library match patterns passed via the -p parameter?

I am running the following command to run only the tests located inside the file called test_CO2.py

python3.7 -m unittest discover -s some_path/tests/ -p "*CO2*"

My folder structure looks like the following:

some_path/tests/
  CO2
    test_CO2.py
  battery
    test_battery.py
  tank
    test_tank.py

I want to specify the tests that are ran. If for example I only wish to test the tank and CO2 code how can I do that? I thought of passing the following regex: \w*(CO2|tank)\w*.py which fails to find any tests.

I am thinking that the pattern passed in to the -p option does not accept regex. How, then can I specify the tests I wish to run?

like image 954
M.Nar Avatar asked Oct 15 '25 08:10

M.Nar


1 Answers

Normally, everything you pass via the -p parameter into unittest is processed via TestLoader._match_path() method which then invokes chain of functions fnmatch()fnmatchcase()_compile_pattern()translate() from fnmatch library.

The translate() function translates your original -p argument into a regex, which is then used for name-matching.

The docs for fnmatch() function state this:

Patterns are Unix shell style:
*       matches everything
?       matches any single character
[seq]   matches any character in seq
[!seq]  matches any char not in seq

From what I can see, this is the extent of what it can do. All other characters are escaped to be matched literally.

Example: I passed regex a|b as the pattern. The translate() function returned final regex in the form (?s:p\|m)\Z. There the pipe character became escaped.

If you're extra curious, go see fnmatch lib's translate() function here - if you want to know the exact process of translating your "glob-like" patterns into the final regex.

like image 63
Smuuf Avatar answered Oct 17 '25 00:10

Smuuf