Python 的 unittest 库如何匹配通过 -p 参数传递的模式?

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

我正在 运行 将以下命令 运行 仅用于位于名为 test_CO2.py

的文件中的测试

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

我的文件夹结构如下所示:

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

我想指定 运行 的测试。例如,如果我只想测试油箱和 CO2 代码,我该怎么做?我想通过以下正则表达式: \w*(CO2|tank)\w*.py 找不到任何测试。

我认为传递给 -p 选项的模式不接受正则表达式。那么如何指定我希望的测试 运行?

通常,您通过 -p 参数传递给 unittest 的所有内容都通过 TestLoader::_match_path() method which then invokes chain of functions fnmatch()fnmatchcase()_compile_pattern()translate() from fnmatch library 处理。

translate() 函数将您原来的 -p 参数转换为正则表达式,然后用于名称匹配。

fnmatch() 函数的文档说明了这一点:

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

据我所知,这就是它能做的事情。 所有其他字符都转义为按字面匹配

示例: 我将正则表达式 a|b 作为模式传递。 translate() 函数以 (?s:p\|m)\Z 的形式返回最终的正则表达式。 管道字符被转义

如果您特别好奇,请查看 fnmatch lib 的 translate() 函数 here - 如果您想知道将 "glob-like" 模式转换为的确切过程最终的正则表达式。

我想出了如何绕过 unittest 的这个限制。

我可以 运行 使用 python3.7 -m unittest path_to_some_test

进行特定测试
# take regex and find all files that match
# clean up results. i.e. remove './' from output
test_paths_result=()
test_paths=$(find . -regextype posix-extended -regex "${regex}")
for file_path in ${test_paths}; do
  # save clean results to array variable
  test_paths_result+=("${file_path:2}")
done

echo "Running test files that match the following expression: '${regex}'"
python3.7 -m unittest ${test_paths_result[@]}