使用 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,并将 tests extra 安装到每个 conda 环境中。edgetest 将创建三个环境:pandas、numpy 和 all-requirements。在前两个环境中,它将仅升级具有这些名称的相应软件包,而 all-requirements 将同时升级 pandas 和 numpy。接下来,将在每个环境中运行测试命令(默认情况下为 pytest),并将结果报告给用户
或者,如果您愿意,您也可以提供 –export 标志,将更改写入到 setup.cfg 中。
使用插件架构
edgetest 的目标之一是确保易于扩展,这促使我们使用 pluggy。Pluggy 允许扩展或修改核心软件包,从而使 Python 社区可以构建自定义插件来与 edgetest 交互。目前有三个插件:conda、pip-tools 和 hub。
使用 pluggy,我们绘制了几个 hookspec
- edgetest.hookspecs.addoption()
- 此挂钩允许用户将全局或环境级别的挂钩添加到配置架构
- 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,这是一种用于数据监控的开源机器学习技术。