【问题标题】:Does it make sense to install my Python unit tests in site-packages?在站点包中安装我的 Python 单元测试是否有意义?
【发布时间】:2013-01-05 11:00:02
【问题描述】:

我正在开发我的第一个 Python 分发包。我的学习曲线 Python 打包似乎有点趋于平稳,但我仍在努力 几个开放的问题。一个是我是否应该使我的单元测试成为 与我的代码一起安装。

我了解it's important to include tests in a source distribution。我想知道的是我是否应该实际配置它们以进行安装?

我见过至少一个流行的软件包似乎是故意这样做的 (PyHamcrest),以及至少另一个似乎是偶然发生的 (behave)。

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

  • 将我的包单元测试与我的 包码?

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

  • 他们将如何使用已安装的单元测试?像import test; test.run() 什么的 像这样?

【问题讨论】:

  • 在我的脑海中,能够确定一个包是否工作/安装正确会很有用,特别是当您分发到不同的平台和/或具有第三方依赖项可能或可能不会因版本而异。
  • 嗨 Joel,我在这里要问的问题是为什么安装测试而不是仅仅将它们包含在源代码分发中可能有意义。
  • numpy scipy pandas sympy blaze numba skimage 都已在站点包中安装了测试,值得一试
  • @endolith 他们的名字是不同的(例如“numpy_tests”)还是当你import test一个基于安装顺序的废话拍摄时得到的名字?
  • @scanny 他们就像numpy.linalg.testsnumpy.fft.testsscipy.fftpack.testspanda.testssympy.integrals.testsskimage.segmentation.testsblaze.testsnumba.tests跨度>

标签: python unit-testing installation setuptools software-distribution


【解决方案1】:

在我看来,正确的答案是否定的,但你会发现很多发行版都安装了测试。不应安装测试,但应将它们包含在源代码分发中。在我看来,在理想情况下,测试已安装的包应该是包管理器 (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() 在 setup.py 中调用

from setuptools import setup, find_packages

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

MANIFEST.in

recursive-include tests *.py

不会安装测试,但它们将通过我们的MANIFEST.in 包含在源代码分发中。

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

  • 当您执行setup.py 时,包含setup.py 的目录会隐式添加到python 路径中。这意味着在您的setup.py 中,如果它的包与setup.py 位于同一目录中,您可能会意外且不正确地从您的库中导入内容。通过将my_lib 包放入src,我们可以避免这个问题。
  • 您可以轻松地使用分布式测试源来测试分布式库源和已安装的库:

    • 当您使用setup.py test 运行测试时,setup() 调用的package_dir={'': 'src'} 部分保证您的测试将看到您保留在src/my_lib 中的my_lib 库包。
    • 您也可以在没有setup.py 的情况下运行测试。在最简单的情况下,您可以使用python -m unittest 命令来实现。在这种情况下,src 目录不会成为 python 路径的一部分,因此您可以使用此方法测试已安装的库版本,而不是 src 中的源代码。

【讨论】:

  • 方法 3 布局避免的陷阱在 pytest 良好集成实践中也有所描述:docs.pytest.org/en/latest/… 我在爱上这些之后开始关注它。
【解决方案2】:

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

在我发现安装了测试的少数案例中,结果证明都是意外,并且比人们想象的更容易犯错误而没有注意到它。

事情是这样发生的:

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

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

【讨论】:

  • 顺便问一下,您如何使用源代码分发版中的测试来测试您的软件包安装?我的意思是有一个特征命令行或函数调用来做到这一点?
  • the handful of cases I found你还记得哪些?
【解决方案3】:

虽然我不是专家,但我想分享一下我的意见。

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2014-05-11
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多