首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发运行测试

并发运行测试
EN

Stack Overflow用户
提问于 2019-06-04 17:03:42
回答 3查看 3.2K关注 0票数 10

我想使用异步(/curio/trio)和pytest同时运行几个测试,但是我找不到关于这个的任何信息。我需要自己安排吗?如果我这样做了,有什么方法可以将(子)测试用例分离出来吗?

下面是一个我正在尝试的小玩具例子:

代码语言:javascript
复制
import pytest
import time
import asyncio

pytestmark = pytest.mark.asyncio
expected_duration = 1
accepted_error = 0.1

async def test_sleep():
    start = time.time()
    time.sleep(expected_duration)
    duration = time.time() - start
    assert abs(duration-expected_duration) < accepted_error

async def test_async_sleep():
    start = time.time()
    await asyncio.sleep(expected_duration)
    duration = time.time() - start
    assert abs(duration-expected_duration) < accepted_error
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-05 06:51:02

不幸的是,pytest在内部的工作方式,不能在同一个调用trio.run/asyncio.run/curio.run.的情况下同时运行多个测试(在某些方面,这也很好-它可以防止测试之间的状态泄漏,并且使用trio至少可以让您为不同的测试配置不同的trio,例如设置一个测试使用自动跳转时钟,而另一个测试不使用。)

当然,最简单的选择是使用pytest-xdist在单独的线程中运行测试。您仍然可以在每个测试内部使用异步,所有这些异步库都支持在不同的线程中运行不同的循环。

如果您确实需要使用异步并发,那么我认为您必须编写一个pytest测试函数,然后在该函数中执行您自己的调度和并发。如果您这样做,那么从pytest的角度来看,只有一个测试,因此很难获得很好的每次测试输出。我想你可以尝试使用热试验-分试验

票数 8
EN

Stack Overflow用户

发布于 2020-03-25 06:38:03

现在有https://github.com/willemt/pytest-asyncio-cooperative了。

现在,2020-03-25的限制相当大--您必须确保您的测试不共享anything (从技术上讲,不要共享可变状态),也不能使用mock.patch (技术上不要模拟其他测试可能使用的任何东西)。

您可以继续在https://github.com/pytest-dev/pytest-asyncio/issues/69上进行讨论,我认为这很难,但可以找到一种方法来标记每个夹具以允许或不允许并发使用,并安排测试以保留这些限制。

票数 5
EN

Stack Overflow用户

发布于 2019-06-05 08:37:52

正如纳撒尼尔所建议的那样,使用pytest-子测试似乎是一个可行的解决方案。下面是如何使用trio来解决这个问题,它对名称以io_开头的每个函数运行子测试。

代码语言:javascript
复制
import pytest
import sys
import trio
import inspect
import re
import time


pytestmark = pytest.mark.trio
io_test_pattern = re.compile("io_.*")


async def tests(subtests):

    def find_io_tests(subtests, ignored_names):
        functions = inspect.getmembers(sys.modules[__name__], inspect.isfunction)
        for (f_name, function) in functions:
            if f_name in ignored_names:
                continue
            if re.search(io_test_pattern, f_name):
                yield (run, subtests, f_name, function)

    async def run(subtests, test_name, test_function):
        with subtests.test(msg=test_name):
            await test_function()

    self_name = inspect.currentframe().f_code.co_name
    async with trio.open_nursery() as nursery:
        for io_test in find_io_tests(subtests, {self_name}):
            nursery.start_soon(*io_test)


accepted_error = 0.1

async def io_test_1():
    await assert_sleep_duration_ok(1)

async def io_test_2():
    await assert_sleep_duration_ok(2)

async def io_test_3():
    await assert_sleep_duration_ok(3)

async def io_test_4():
    await assert_sleep_duration_ok(4)

async def assert_sleep_duration_ok(duration):
    start = time.time()
    await trio.sleep(duration)
    actual_duration = time.time() - start
    assert abs(actual_duration - duration) < accepted_error

运行python -m pytest -v输出:

代码语言:javascript
复制
============================ test session starts =============================
platform darwin -- Python 3.7.0, pytest-4.6.2, py-1.8.0, pluggy-0.12.0
plugins: asyncio-0.10.0, trio-0.5.2, subtests-0.2.1
collected 1 item

tests/stripe_test.py::tests PASSED                                     [100%]
tests/stripe_test.py::tests PASSED                                     [100%]
tests/stripe_test.py::tests PASSED                                     [100%]
tests/stripe_test.py::tests PASSED                                     [100%]
tests/stripe_test.py::tests PASSED                                     [100%]

========================== 1 passed in 4.07 seconds ==========================

这并不完美,因为这个百分比只是相对于测试的数量而不是子测试的数量(即。io_*在这里标记了函数),但这似乎是一个好的开始。

还请注意,time.time()是使用的,所以它对三重和异步都有意义,但是在实际的用例中,应该使用trio.current_time()

可以使用异步实现相同的测试,基本上必须替换以下三种东西:

  • pytestmark = pytest.mark.triopytestmark = pytest.mark.asyncio
  • yield (run, subtests, f_name, function)yield run(subtests, f_name, function)
  • 最后,托儿所循环应该替换为如下内容:
代码语言:javascript
复制
await asyncio.gather(*find_io_tests(subtests, {self_name}))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56448398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档