15

我正在开发我的第一个 Python 分发包。我在 Python 打包方面的学习曲线似乎正在趋于平稳,但我仍在努力解决一些悬而未决的问题。一个是我是否应该让我的单元测试与我的代码一起安装。

我知道在源代码分发中包含测试很重要。我想知道我是否应该实际配置它们以进行安装?

我已经看到至少一个流行的包似乎是故意这样做的(PyHamcrest),以及至少另一个似乎是偶然这样做的(表现)。

所以我的(多部分)问题是这样的:

  • 将我的包单元测试与我的包代码一起安装是否有意义?

  • 如果是这样,用例是什么?谁会使用它们以及用于什么目的?也就是说,谁会使用它们而不是完全乐意下载源分发并运行python setup.py test呢?

  • 他们将如何使用已安装的单元测试?像import test; test.run()或类似的东西?

4

3 回答 3

13

在我看来,正确的答案是否定的,但你会发现很多安装测试的发行版。不应安装测试,但应将它们包含在源代码分发中。在我看来,在理想情况下,测试安装的包应该是包管理器(pip)执行的任务,并且site-packages目录不应该被测试源污染。

我最近研究了这个主题并从各种来源收集了信息,并发现了几种不同的方法来构建包含库源和测试的发行版的目录/包层次结构。这些结构中的大多数似乎已经过时了,它们的发明是为了解决当时旧分发系统的不完整功能集。不幸的是,许多在线资源(较旧的博客文章/文档)仍在宣传过时的方法,因此通过在线搜索很容易找到过时的分发方法/教程。

假设您有一个名为“my_lib”的库,并且您想要构建您的发行版的源代码。我将展示两种流行且看似过时的方式来构建您的发行版,以及第三种我发现是最通用的方式。第三种方法也可能已经过时,但这是我在发布此答案时所知道的最好的方法。;-)

方法#1

(有意或无意地)安装测试的发行版通常使用这种方法。

等级制度

+- my_lib
|  +- __init__.py
|  +- source1.py
|  +- source2.py
|  +- tests
|     +- __init__.py
|     +- test_1.py
|     +- test_2.py
+- setup.py

方法#2

未安装测试,但它们应通过MANIFEST.in文件包含在源代码分发中。

等级制度

+- my_lib
|  +- __init__.py
|  +- source1.py
|  +- source2.py
+- tests
|  +- __init__.py
|  +- test_1.py
|  +- test_2.py
+- setup.py

方法#3(我更喜欢这个。)

这与方法#2 非常相似,但略有不同(src目录)。

等级制度

+- src
|  +- my_lib
|     +- __init__.py
|     +- source1.py
|     +- source2.py
+- tests
|  +- __init__.py
|  +- test_1.py
|  +- test_2.py
+- setup.py

setup.py 中的 setup() 调用

from setuptools import setup, find_packages

setup(
    ...
    packages=find_packages('src'),
    package_dir={'': 'src'},
    ...
)

清单文件

recursive-include tests *.py

不会安装测试,但它们将通过我们的MANIFEST.in.

在方法#3 的情况下,您的src目录通常只包含一个包,该包是您的 lib 的根目录。将my_lib包放入src目录(目录而不是包,因此您不需要src/__init__.py)具有以下好处:

  • 执行时setup.py包含的目录setup.py会隐式添加到 python 路径中。这意味着setup.py如果它的包与setup.py. 通过将my_lib包放入src我们可以避免这个问题。
  • 您可以轻松地使用分布式测试源来测试分布式库源和已安装的库:

    • 当您使用调用setup.py testpackage_dir={'': 'src'}一部分运行测试时,可以setup()保证您的测试将看到您my_lib保留的库包src/my_lib
    • 您也可以在没有setup.py. 在最简单的情况下,您可以使用python -m unittest命令执行此操作。在这种情况下,srcdir 不会是 python 路径的一部分,因此您可以使用此方法来测试已安装的库版本,而不是src.
于 2016-04-13T14:29:43.580 回答
11

在研究了这个问题之后,直到更有经验的人有一点时间来权衡,我的理解是简单的答案是:“不,不应该安装单元测试,只包含在源代码分发中”。

在我发现安装测试的少数几个案例中,所有结果都是偶然的,而且在没有注意到的情况下犯错误比人们想象的要容易。

这是如何发生的:

  1. packages=find_packages()参数在 setup.py 中使用,因此无需明确列出即可找到包。
  2. test文件夹被制成一个包(通过添加__init__.py),因此测试可以使用相对命名(如from .. import pkg.mod)引用他们测试的模块。
  3. setuptoolstest与项目中的其他软件包一起作为单独的软件包安装。请注意,这意味着您可以import test在 python 解释器中执行它并且它可以工作,几乎可以肯定不是您想要的,特别是因为很多其他人使用该名称作为他们的测试目录:)

解决方法是使用设置:packages=find_packages(exclude=['test'])防止安装您的测试目录。

于 2013-01-31T01:44:26.430 回答
2

但是我不是专家,我想分享一下我的观点。

如果我预计某些事情可能会因外部原因而失败,我总是会将测试与代码放在一起。无论是位顺序、奇怪的时区、字符编码、24 位整数还是您可以遇到并进行测试的任何其他奇怪的东西。

谁会不乐意下载源代码并运行测试?也许有些debian用户的包被从源中剥离(我知道你在谈论 python,但让我有点笼统)并且你的库有时会由于系统中的一些奇怪的事情而失败。

如果您的测试仅确保内部健全,我会跳过附加它们,因为没有源它们没有多大价值,因为您永远不会更改库的内部结构。

就个人而言,我听说过一个失败的事情,因为它被移到了一些具有不同位顺序的 IBM 机器上。我不记得它是依赖于位操作还是有一些预先计算和静态缓存的东西。但有时明智的做法是检查您是否加载了您认为已保存的内容。

编辑:也许改写它会更好。当您觉得可能存在可移植性警告时,我会安装测试。我认为当你在不同的系统上部署东西时检查东西总是好的。

于 2013-01-22T09:14:40.383 回答