【问题标题】:How to organize python test in a way that I can run all tests in a single command?如何以可以在单个命令中运行所有测试的方式组织 python 测试?
【发布时间】:2008-12-14 16:52:50
【问题描述】:

目前我的代码按以下树形结构组织:

src/
    module1.py
    module2.py
    test_module1.py
    test_module2.py
    subpackage1/
        __init__.py
        moduleA.py
        moduleB.py
        test_moduleA.py
        test_moduleB.py

module*.py 文件包含源代码,test_module*.py 包含相关模块的TestCases。

使用以下命令,我可以运行包含在单个文件中的测试,例如:

$ cd src
$ nosetests test_filesystem.py
..................
----------------------------------------------------------------------
Ran 18 tests in 0.390s

OK

如何运行所有测试?我尝试使用nosetests -m 'test_.*',但它不起作用。

$cd src
$ nosetests -m 'test_.*'

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

OK

谢谢

【问题讨论】:

    标签: python unit-testing python-nose


    【解决方案1】:

    您是分开还是混合测试和模块可能是个人喜好问题,尽管我强烈主张将它们分开(设置原因、代码统计等)。

    当你使用鼻子测试时,确保所有带有测试的目录都是真正的包:

    src/
        module1.py
        module2.py
        subpackage1/
            __init__.py
            moduleA.py
            moduleB.py
    tests/
        __init__.py
        test_module1.py
        test_module2.py
        subpackage1/
            __init__.py
            test_moduleA.py
            test_moduleB.py
    

    这样,您只需在顶层目录中运行nosetests 即可找到所有测试。但是,您需要确保 src/PYTHONPATH 上,否则所有测试都会因缺少导入而失败。

    【讨论】:

      【解决方案2】:

      如果它们都以test 开头,那么只需nosetest 就可以了。 Nose 会自动搜索任何以“test”开头的文件。

      【讨论】:

      • 我发现了问题,nosetests 跳过它们,因为它们是可执行文件。我修复了重置可执行权限位并从 subversion 属性中删除 svn:executable 属性。
      • --exe 选项将防止鼻子测试跳过可执行文件。
      • 可能值得考虑转移到nose2 而不是nosetestnose2.readthedocs.io/en/latest/getting_started.html
      【解决方案3】:

      我不知道鼻子测试,但您可以使用标准的单元测试模块来实现。你只需要在你的根目录下创建一个test_all.py 文件,然后导入你所有的测试模块。在你的情况下:

      import unittest
      import test_module1
      import test_module2
      import subpackage1
      if __name__ == "__main__":
          allsuites = unittest.TestSuite([test_module1.suite(), \
                                      test_module2.suite(), \
                                      subpackage1.test_moduleA.suite(), \
                                      subpackage1.test_moduleB.suite()])
      

      每个模块都应提供以下功能(以具有两个单元测试的模块为例:Class1Class2):

      def suite():
          """ This defines all the tests of a module"""
          suite = unittest.TestSuite()
          suite.addTest(unittest.makeSuite(Class1))
          suite.addTest(unittest.makeSuite(Class2))
          return suite
      if __name__ == '__main__':
         unittest.TextTestRunner(verbosity=2).run(suite())
      

      【讨论】:

      • 这是我一直在寻找的,除了我认为您应该在每个套件名称后省略()(至少在 Python 2.6.5 下)。
      • Python 2.7 有一种自动查找测试模块/包的方法,这似乎比记住将它们显式添加到 test_all.py 更容易维护。见docs.python.org/library/unittest.html#test-discovery
      【解决方案4】:

      这可能是一个激烈争论的话题,但我建议您将测试与模块分开。设置这样的东西...

      使用setup.py 将它们安装到系统路径中(或者您可以修改环境变量以避免需要“安装”步骤)。

      foo/
          module1.py
          module2.py
          subpackage1/
              __init__.py
              moduleA.py
              moduleB.py
      

      现在任何地方的任何 python 脚本都可以访问这些模块,而不是依赖于在本地目录中找到它们。像这样把你的测试放在一边:

      tests/
          test_module1.py
          test_module2.py
          test_subpackage1_moduleA,py
          test_subpackage2_moduleB.py
      

      我不确定你的nosetests 命令,但现在你的测试都在同一个目录中,编写一个简单地将所有其他测试导入同一个目录中的包装脚本变得容易得多。或者,如果这不可能,您至少可以使用一个简单的bash 循环来逐个获取您的测试文件:

      #!/bin/bash
      cd tests/
      for TEST_SCRIPT in test_*.py ; do
          nosetests -m $TEST_SCRIPT
      done
      

      【讨论】:

      • 我建议将程序的包结构反映在测试目录中。否则随着程序的增长,测试目录会变得一团糟。
      【解决方案5】:

      我会回复Testoob

      在单个文件中运行测试就像鼻子:

      testoob test_foo.py
      

      要在多个文件中运行测试,您可以使用 Testoob 收集器创建套件(在每个子包中)

      # src/subpackage?/__init__.py
      def suite():
        import testoob
        return testoob.collecting.collect_from_files("test_*.py")
      

      # src/alltests.py
      test_modules = [
          'subpackage1.suite',
          'subpackage2.suite',
      ]
      
      def suite():
          import unittest
          return unittest.TestLoader().loadTestsFromNames(test_modules)
      
      if __name__ == "__main__":
          import testoob
          testoob.main(defaultTest="suite")
      

      我没有尝试过你的具体场景。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-04
        • 2011-02-10
        • 2013-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-01
        相关资源
        最近更新 更多