跳转到主要内容

一个用于编写内联测试的pytest插件。

项目描述

pytest-inline

License Pypi Release GithubWorkflow

pytest-inline是一个pytest插件,用于编写内联测试。

内联测试是一种新的测试粒度,它使得检查单个程序语句变得更容易。内联测试是一种语句,允许开发者提供任意输入和测试预言机来检查紧邻的前一个语句(该语句不是内联测试)。与通常放置在单独的test_*.py文件中的单元测试不同,内联测试与实际的生产代码一起编写(因此更容易维护)。

目录

  1. 示例
  2. 安装
  3. 使用
  4. API
  5. 性能
  6. 引用

示例

此代码片段中的正则表达式(第7行)检查变量名是否匹配以冒号结尾且至少包含一个数字的模式。为我们编写的针对目标语句(第7行)的内联测试由三个部分组成

  • 使用itest()构造函数声明
  • 使用given()函数调用分配输入
  • 使用check_*()函数调用指定测试预言机
from inline import itest

def get_assignment_map_from_checkpoint(tvars, init_c):
    ...
    for var in tvars:
        name = var.name
        m = re.match("^(.*):\\d+$", name)
        itest().given(name, "a:0").check_eq(m, "a")
        if m is not None:
            name = m.group(1)
    ...

安装

使用pip install pytest-inline安装此插件。

使用

使用pytest .运行工作目录中的所有内联测试。

使用pytest {filename}运行Python文件中的所有内联测试。

API

内联测试的声明

  • itest(test_name, parameterized, repeated, tag, disabled, timeout)
  1. test_name是一个表示测试名称的字符串。默认值是文件名加上测试语句的行号。

  2. parameterized是一个布尔值,表示测试是否是参数化的。默认值是false。

  3. repeated是一个整数,表示测试重复的次数。默认值是1。

  4. tag是一个表示测试标签的字符串。默认值是一个空字符串。

  5. disabled是一个布尔值,表示测试是否被禁用。默认值是false。

  6. timeout是一个浮点数,表示测试运行到超时所需的时间。默认值是-1.0。如果测试超时,它将抛出一个超时异常。

使用assume()调用提供任何假设

  • assume(condition): 检查条件是否成立,如果条件不成立,则测试不会运行。

    如果添加了assume检查,它必须发生在任何given语句之前,并且只能添加一个。

    以下是一个玩具示例。它仅仅说明了如何使用assume语句调用。可以在assume语句中使用更复杂的逻辑,例如检查给定的系统版本,并假设只有当假设的系统版本为真时才运行测试。

    def FileHeader(self):
        dt = self.date_time
        dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
        itest().assume(2 < 4).given(dt, (1980, 1, 25, 17, 13, 14)).check_eq(dosdate, 57)
    

使用given()调用提供测试输入

  • given(variable, value): 将值分配给变量。

    请注意,可以添加任意数量的given语句。以下是一个此功能的简单示例。此外,第一个given调用必须在一个itest()声明或一个assume()调用之前进行,如果添加了它。

    def multiple_givens(a, c):
        b = a + c
        itest().given(a, 2).given(c, a + 1).check_true(b == 5)
    

使用check()调用指定测试预言机

  • check_eq(actual_value, expected_value): 检查实际值是否等于预期值。

  • check_neq(actual_value, expected_value): 检查实际值是否不等于预期值。

  • check_true(expr): 检查布尔表达式是否为真。

  • check_false(expr): 检查布尔表达式是否为假。

  • check_none(variable): 检查变量是否为none。

  • check_not_none(variable): 检查变量是否不为none。

  • check_same(actual_value, expected_value): 检查实际值和预期值是否引用同一对象。

  • check_not_same(actual_value, expected_value): 检查实际值和预期值是否引用不同的对象。

对于给定的内联测试调用,只能指定一个测试预言机。

性能

内联测试通常运行得很快,因为每个内联测试只检查一个语句。请注意,当不运行测试时,内联测试的行为就像空函数调用一样,将它们放入生产代码中的开销是可以忽略不计的。

我们评估了pytest-inline在一份数据集上的性能,该数据集包含87个内联测试,这些测试是为31个开源项目中的50个示例中的80条语句编写的。主要发现总结如下,更多详情请参阅[我们的论文][paper-url]。我们进行了3次实验

  1. 以独立模式运行内联测试。每个内联测试的平均耗时为0.147秒。大部分时间都花费在启动和解析文件上,如果有更多内联测试在文件中,这可以优化。因此,我们也对内联测试进行了10次、100次、1000次的复制,每次内联测试的平均时间分别降低到0.015秒、0.002秒、0.001秒。

  2. 与单元测试一起运行内联测试。与仅运行单元测试相比,平均开销仅为0.007倍。即使将内联测试复制1000次(使得内联测试的总数与单元测试的总数相匹配),平均开销也只有0.088倍。

  3. 与单元测试一起运行内联测试,但禁用pytest-inline。这是为了模拟内联测试在生产代码中的成本。开销可以忽略不计:当我们不复制内联测试时,得到的数据是-0.001倍(由于噪声),只有当复制内联测试1000次时,才增加到0.019倍。

所有内联测试的API在非测试模式下都表现为空函数调用,总是返回一个虚拟对象,例如,check_eq定义为:def check_eq(self, ...): return self。根据我们的实验观察,这通常不会产生可忽略不计的开销,但请注意,每次遇到内联测试时都要支付成本,因此如果内联测试位于将被多次执行的代码部分(例如,循环)中,这可能会累积。

引用

标题:内联测试

作者:Yu LiuPengyu NieOwolabi LegunsenMilos Gligoric

@inproceedings{LiuASE22InlineTests,
  title =        {Inline Tests},
  author =       {Yu Liu and Pengyu Nie and Owolabi Legunsen and Milos Gligoric},
  pages =        {1--13},
  booktitle =    {International Conference on Automated Software Engineering},
  year =         {2022},
}

标题:pytest-inline

作者:Yu LiuZachary ThurstonAlan HanPengyu NieMilos GligoricOwolabi Legunsen

@inproceedings{LiuICSE23PytestInline,
  title =        {pytest-inline: An Inline Testing Tool for Python},
  author =       {Yu Liu and Zachary Thurston and Alan Han and Pengyu Nie and Milos Gligoric and Owolabi Legunsen},
  pages =        {1--4},
  booktitle =    {International Conference on Software Engineering, DEMO},
  year =         {2023},
}

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

pytest-inline-1.0.5.tar.gz (28.4 kB 查看散列)

上传时间

构建分布

pytest_inline-1.0.5-py3-none-any.whl (23.7 kB 查看散列)

上传时间 Python 3

由以下组织支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面