为什么运行“ setup.py test”会运行我的控制台脚本?

时间:2018-09-28 06:12:58

标签: python setuptools

我非常简单的示例项目包含:

addtest/
  setup.py
  addtest/
    __init__.py
    __main__.py
    app.py

我的app.py就是:

def main():
    raise SystemExit("Command line entry point called.")

我的__main__.py就是:

from addtest.app import main
main()

我的setup.py包含:

from setuptools import setup, find_packages

setup(
    name='AddTest',
    version='1.0',
    packages=find_packages(),

    entry_points={
        'console_scripts': ['addtest = addtest.app:main']
    },
)

我希望运行python setup.py test不会做任何事情,因为没有编写任何单元测试。但是,在干净的virtualenv中运行它(在Ubuntu 18.04.1上为Python 3.6.6)可以使我:

$ python setup.py test
running test
running egg_info
writing AddTest.egg-info/PKG-INFO
writing dependency_links to AddTest.egg-info/dependency_links.txt
writing entry points to AddTest.egg-info/entry_points.txt
writing top-level names to AddTest.egg-info/top_level.txt
reading manifest file 'AddTest.egg-info/SOURCES.txt'
writing manifest file 'AddTest.egg-info/SOURCES.txt'
running build_ext
Command line entry point called.

请注意Command line entry point called.,这意味着它正在调用从我的__main__.py生成的控制台脚本(或者可能只是调用python -m addtest)。

为什么setup.py要在我希望它运行测试时调用控制台脚本?进一步检查脚本的执行情况,发现sys.argv['setup.py','test']-为什么?

3 个答案:

答案 0 :(得分:2)

setuptools中的测试扫描程序将在子目录中的任何 *.py文件中查找测试,__init__.py除外。是的,其中包括__main__.py,它将在其上调用__import__(),从而使其主要套件得以执行。

如果您希望能够运行python -m addtest并让其运行您的__main__.py代码,则可能需要添加标准的“仅在这确实是主要保护时才运行”保护:

if __name__ == "__main__":
   ...

(然后,如果您执行python -m,则代码将运行,但是如果文件由setup.py test加载,则将不会运行)

答案 1 :(得分:1)

setuptools docs说明了默认情况下setuptools如何扫描单元测试。

因为正如您所说,没有编写或指定任何单元测试,所以setuptools可以使用默认行为。

来自setuptools docs的一些参考资料对此进行了详细说明,并在下面指定了如何设置测试套件:

  1.   

    test_loader如果您想使用   查找要运行的测试的方法与通常的安装工具不同   使用时,可以在此参数中指定模块名称和类名称。   
    ...
      模块名称和类名称必须用:分隔。此参数的默认值为"setuptools.command.test:ScanningLoader"。如果要使用默认的单元测试行为,则可以将"unittest:TestLoader"指定为test_loader参数。 这将防止自动扫描子模块和子包。

  2.   

    ... test_suite命名unittest.TestCase子类(或包)的字符串   或包含其中一个或多个模块的模块,或此类模块的方法   子类),或者命名一个可以不带参数调用的函数   并返回unittest.TestSuite

    如果命名套件是模块,则   该模块具有一个additional_tests()函数,该函数被调用,并且   结果将添加到要运行的测试中。如果命名套件是   包,则将所有子模块和子包递归添加到   整体测试套件。

         

    指定此参数可启用test命令来运行   指定的测试套件,例如通过 setup.py test 。请参阅   下面的test命令以获取更多详细信息。   
    ...

         setup(
         # ...
         test_suite="my_package.tests.test_all"
     )

这与该线程上的another answer一起为您提供了至少两个选项,以确保python setup.py test不运行控制台脚本:

  1. 配置setuptools查找测试套件的方式。
  2. if __name__ == "__main__":周围添加main()

您正在使用的单元测试库可能会提供另一个选项。例如,Pytestintegration guide for setuptools用其自己的命令替换了test命令。


关于系统参数

sys.argv['setup.py','test'],因为您用参数python调用了setup.py test

答案 2 :(得分:0)

我认为您必须在setup.py中指定测试的入口点。否则,它将传递给main.py。