unittest.py与trace.py不能很好地配合-为什么? [英] unittest.py doesn't play well with trace.py - why?

查看:94
本文介绍了unittest.py与trace.py不能很好地配合-为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

哇。我今晚发现使用 unittest 模块编写的Python单元测试不能很好地与 trace 下的覆盖率分析配合使用模块。这是在 foobar.py 中最简单的单元测试:

  import unittest 

class Tester(unittest.TestCase):
def test_true(self):
self.assertTrue(True)

如果__name__ == __main__:
unittest.main()

如果我使用 python foobar.py ,我得到以下输出:

 
---------------------------------------------- ------------------------
以0.000s进行1次测试

OK

太好了。现在,我也想执行覆盖率测试,因此我再次使用 python -m trace --count -C运行它。 foob​​ar.py ,但现在我明白了:

  --------- -------------------------------------------------- ----------- 
在0.000s内进行了0次测试

OK

不,Python,这不行-您没有运行我的测试!似乎是在 trace 上下文中运行,以某种方式加强了 unittest 的测试检测机制。这是我想出的(疯狂的)解决方案:

  import unittest 

class Tester(unittest。 TestCase):
def test_true(self):
self.assertTrue(True)

class Insane(object):
pass

如果__name__ == __main__:
module = Insane()
for k,v in locals()。items():
setattr(module,k,v)

unittest.main(module)

这基本上是一种变通方法,可以简化抽象的,无法命名的伪造其副本的顶级模块的名称。然后,我可以将该名称传递给 unittest.main(),以避开 trace 对它产生的任何影响。无需显示输出;



所以,我有两个问题:


  1. 这是怎么回事?为什么 trace unittest 搞砸了?


  2. 有没有更容易和/或更少疯狂的方法来解决此问题?



解决方案

一个更简单的解决方法是将模块的名称显式传递给 unittest.main

  import unittest 

class Tester(unittest.TestCase):
def test_true(self):
self.assertTrue(True)

如果__name__ == __main__:
unittest.main(module ='foobar')

trace 弄乱了 unittest 中的测试发现,因为 trace如何加载正在运行的模块。 trace 读取模块源代码,对其进行编译,然后在将 __ name __ 全局设置为<$的上下文中执行该代码。 c $ c>'__ main __'。这足以使大多数模块像它们被称为主模块一样工作,但实际上并不会更改在Python解释器中注册为 __ main __ 的模块。当 unittest 要求 __ main __ 模块扫描测试用例时,实际上得到了跟踪从命令行调用的模块,该模块当然不包含单元测试。



coverage.py 采用了另一种方法来实际替换 sys.modules 中哪个模块称为 __ main __ 。 / p>

Wow. I found out tonight that Python unit tests written using the unittest module don't play well with coverage analysis under the trace module. Here's the simplest possible unit test, in foobar.py:

import unittest

class Tester(unittest.TestCase):
    def test_true(self):
        self.assertTrue(True)

if __name__ == "__main__":
    unittest.main()

If I run this with python foobar.py, I get this output:

 .
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Great. Now I want to perform coverage testing as well, so I run it again with python -m trace --count -C . foobar.py, but now I get this:

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

No, Python, it's not OK - you didn't run my test! It seems as though running in the context of trace somehow gums up unittest's test detection mechanism. Here's the (insane) solution I came up with:

import unittest

class Tester(unittest.TestCase):
    def test_true(self):
        self.assertTrue(True)

class Insane(object):
    pass

if __name__ == "__main__":
    module = Insane()
    for k, v in locals().items():
        setattr(module, k, v)

    unittest.main(module)

This is basically a workaround that reifies the abstract, unnameable name of the top-level module by faking up a copy of it. I can then pass that name to unittest.main() so as to sidestep whatever effect trace has on it. No need to show you the output; it looks just like the successful example above.

So, I have two questions:

  1. What is going on here? Why does trace screw things up for unittest?

  2. Is there an easier and/or less insane way to get around this problem?

解决方案

A simpler workaround is to pass the name of the module explicitly to unittest.main:

import unittest

class Tester(unittest.TestCase):
    def test_true(self):
        self.assertTrue(True)

if __name__ == "__main__":
    unittest.main(module='foobar')

trace messes up test discovery in unittest because of how trace loads the module it is running. trace reads the module source code, compiles it, and executes it in a context with a __name__ global set to '__main__'. This is enough to make most modules behave as if they were called as the main module, but doesn't actually change the module which is registered as __main__ in the Python interpreter. When unittest asks for the __main__ module to scan for test cases, it actually gets the trace module called from the command line, which of course doesn't contain the unit tests.

coverage.py takes a different approach of actually replacing which module is called __main__ in sys.modules.

这篇关于unittest.py与trace.py不能很好地配合-为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆