You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTest异步测试未执行求助:断点无效、无输出却显示通过

问题:异步测试用例未实际执行,断点无法触发

测试异步函数时编写了异步测试用例,遇到以下问题:

  • PyCharm中设置的断点完全不触发
  • 控制台无预期输出,测试耗时0秒
  • PyTest标记测试为PASSED,但代码显然未实际执行

测试代码

import unittest.mock
import pytest
from app.listener import ListenerCog


class ListenerCogTestCase(unittest.TestCase):
    def setUp(self):
        # 创建mock discord.Client对象
        self.client = unittest.mock.Mock()

        # 创建ListenerCog实例并传入mock client作为bot属性
        self.listener_cog = ListenerCog(self.client)

    @pytest.mark.asyncio
    async def test_on_ready(self):
        # 调用ListenerCog实例的on_ready方法
        await self.listener_cog.on_ready()

        # 断言控制台输出了"Running!"
        self.assertIn("Running!", self.stdout.getvalue())

已尝试的无效方法

  • 在PyCharm注册表中启用python.debug.asyncio.repl
  • 为pytest添加参数--capture=no -s和--no-conv

解决方案

核心问题:unittest与pytest异步标记不兼容

你的测试类继承了unittest.TestCase,但同时使用了pytest的@pytest.mark.asyncio装饰器。unittest框架无法识别pytest的异步标记,导致测试方法被直接跳过,因此出现"耗时0秒、PASSED但代码未执行"的现象。

方案1:改用pytest风格的测试类/函数式测试

放弃unittest.TestCase,改用普通类或函数式测试,让pytest正常处理异步逻辑:

类式测试示例

import unittest.mock
import pytest
from app.listener import ListenerCog
import sys
from io import StringIO

class ListenerCogTestCase:
    def setUp(self):
        self.client = unittest.mock.Mock()
        self.listener_cog = ListenerCog(self.client)
        # 捕获标准输出
        self.original_stdout = sys.stdout
        sys.stdout = self.stdout = StringIO()

    def tearDown(self):
        # 恢复标准输出
        sys.stdout = self.original_stdout

    @pytest.mark.asyncio
    async def test_on_ready(self):
        await self.listener_cog.on_ready()
        # 重置输出指针到开头
        self.stdout.seek(0)
        assert "Running!" in self.stdout.read()

函数式测试示例(更推荐)

import unittest.mock
import pytest
from app.listener import ListenerCog
import sys
from io import StringIO

@pytest.fixture
def listener_cog():
    client = unittest.mock.Mock()
    return ListenerCog(client)

@pytest.fixture
def captured_stdout(monkeypatch):
    # 用pytest的monkeypatch捕获stdout
    stdout = StringIO()
    monkeypatch.setattr(sys, "stdout", stdout)
    return stdout

@pytest.mark.asyncio
async def test_on_ready(listener_cog, captured_stdout):
    await listener_cog.on_ready()
    captured_stdout.seek(0)
    assert "Running!" in captured_stdout.read()

方案2:保留unittest框架,使用asynctest库

如果你需要继续使用unittest.TestCase,可以安装asynctest库来支持异步测试:

  1. 安装依赖:pip install asynctest
  2. 修改测试类:
import unittest.mock
import asynctest
from app.listener import ListenerCog
import sys
from io import StringIO

class ListenerCogTestCase(asynctest.TestCase):
    async def setUp(self):
        self.client = unittest.mock.Mock()
        self.listener_cog = ListenerCog(self.client)
        self.original_stdout = sys.stdout
        sys.stdout = self.stdout = StringIO()

    async def tearDown(self):
        sys.stdout = self.original_stdout

    async def test_on_ready(self):
        await self.listener_cog.on_ready()
        self.stdout.seek(0)
        self.assertIn("Running!", self.stdout.read())

额外注意事项

  • 确保PyCharm的测试运行配置选择pytest而非unittest,避免框架识别错误
  • 原代码中self.stdout未初始化,需在setUp中添加标准输出捕获逻辑,否则断言会报错

内容的提问来源于stack exchange,提问作者melchoir55

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:50:22