使用 Python 进行前沿依赖测试
任何语言中的依赖项管理都可能是一个挑战,Python 也不例外。像 pip 和 conda 这样的工具使用依赖项解析器来尝试满足给定的要求,但版本冲突常常会阻止安装;当 pip 在 2020 年 10 月引入新的解析器时,这个问题变得更加明显。上游软件包的新版本可能会破坏您的代码,如果您有一长串的传递性依赖项,那么追查罪魁祸首可能更具挑战性。
edgetest 是一个开源的基于插件的 Python 软件包,旨在帮助开发人员根据现有依赖项的新版本测试他们的代码。edgetest 通过以下方式帮助减轻依赖项管理的负担: - 创建一个虚拟环境; - 将您的本地软件包安装到环境中; - 升级指定的依赖项软件包;以及 - 运行您的测试命令(例如 pytest)。
维护成本和环境管理已成为 pip 解析器“运行引擎”的一部分。现在,edgetest 可以通过自动化最前沿的依赖项测试来帮助降低软件包的维护成本。例如,如果您依赖 pandas>=0.25.1,<=1.0.0,edgetest 将根据最新的 pandas 版本(撰写本文时为 1.4.1)测试您的项目。通过有效的测试套件,您将知道是否可以安全地升级到 pandas>=0.25.1,<=1.4.1。edgetest 将根据测试结果报告是否可以安全升级。它将为每个依赖项单独执行此操作,然后再升级所有上游软件包,以识别任何潜在的交互。
我们为什么构建 edgetest
在 pip 于 2020 年 10 月引入依赖项解析器之后,我们决定对 Capital One 的内部项目采取更具规范性的依赖项固定方法。具体来说,这包括为所有软件包的任何直接依赖项添加下限和上限。然而,这个决定增加了一种新的维护成本:更新固定。我们需要一种自动化方法来帮助修复软件包中发现的安全漏洞,并以可扩展的方式继续支持最新版本的依赖项。鉴于我们的团队当时支持的 Python 软件包数量,edgetest 是解决此问题的一个方案。机器学习软件包通常具有复杂的依赖结构,新功能的实验至关重要。虽然模型的实现应始终固定软件包以确保确定性行为和可审计性,但我们不希望工具本身不必要地具有限制性,而是允许其实现具有一定的灵活性。
我们现在可以安排 CI/CD 作业,这些作业会自动对许多内部库运行 edgetest,以运行单元测试并提高依赖项固定,从而确保对最新版本有一定程度的信任。我们应该指出,拥有健壮的单元测试对于充分利用 edgetest 至关重要。
这与 GitHub 的 Dependabot 有何不同?
edgetest 不像 GitHub 那样与特定的版本控制系统绑定。它还通过仅在单元测试通过时升级软件包依赖项来防止意外更新。最后,一些用户希望专注于其依赖树的子集进行更新。有时这些是经常发布的依赖项(例如 boto3),有时这些软件包是其库功能的核心。edgetest 提供多种配置选项,帮助用户创建适用于其用例的测试和升级系统。
edgetest 实战
例如,让我们想象一个简单的 toy_package,如下所示:
要配置 edgetest,我们可以在 setup.cfg 中包含以下内容
并使用以下命令行语句运行:edgetest -c setup.cfg
这将告诉 edgetest 使用 Python 3.9,并将测试额外的安装到每个 conda 环境中。edgetest 将创建三个环境:pandas、numpy 和 all-requirements。在前两个环境中,它将只升级名称相同的相应软件包,而 all-requirements 将升级 pandas 和 numpy。接下来,在每个环境中运行测试命令(pytest 是默认值),并将结果报告给用户。
或者,如果您愿意,也可以提供 --export 标志,为您将更改写入 setup.cfg。
使用插件架构
edgetest 的目标之一是确保易于扩展,这促使我们使用 pluggy。Pluggy 能够扩展或修改核心软件包,使 Python 社区能够构建自定义插件以与 edgetest 交互。目前有三个插件:conda、pip-tools 和 hub。
通过 pluggy,我们规划了几个 hookspecs
- edgetest.hookspecs.addoption()
- 此钩子允许用户向配置 schema 添加全局或环境级别的钩子
- edgetest.hookspecs.path_to_python()
- 此钩子返回 Python 可执行文件的路径
- edgetest.hookspecs.create_environment()
- 此钩子创建虚拟环境。
这些钩子允许用户覆盖和注入他们的自定义代码,以补充或覆盖基本功能。例如,create_environment 钩子支持使用自定义环境管理器,如 conda。下面是基本功能和插件覆盖之间的 hookimpl 比较
下一步
edgetest 最大的好处之一是自动化能力。一个基于 edgetest 构建的 GitHub Action 可供 CI/CD 平台用户使用,并允许您自动化构建、测试和部署依赖项管理。使用 GitHub Action 相对容易,下面是一个在 YAML 中使用该操作的示例
Run-edgetest-action 可以在 GitHub Marketplace 上找到,用户可以在其中搜索添加功能和改进工作流程的工具。更多详细信息可以在 run-edgetest-action 的 README 中找到。
结论
总之,edgetest 是 Capital One 致力于采用“开源优先”的 Python 软件开发方法的典范。edgetest 帮助开发人员根据现有依赖项的新版本测试他们的代码,并通过自动化最前沿的依赖项测试来降低软件包的维护成本。它创建一个虚拟环境,安装您的库,升级指定的依赖项,并运行测试命令。之后,edgetest 将根据测试结果报告是否可以安全升级。我们鼓励读者查看 GitHub 上的 edgetest,了解有关该项目的更多详细信息以及如何为 edgetest 做出贡献。
Capital One 是 Python 软件基金会的骄傲成员,我们的团队在今年早些时候的 PyCon US 上展示了 Data Profiler,这是一种用于数据监控的开源机器学习技术。




