如何在Pytest中为没有return语句的方法创建单元测试?

问题描述 投票:-1回答:2

我正在尝试对一个函数进行pytest,而该类中没有返回值:

# app.py
from utils import DBConnection


class App:
  def add_ticket_watcher(self, ticket_key, watcher_name):
    if ticket_key is None:
      raise ValueError('Ticket key is empty')

    instance = DBConnection()
    instance.save(ticket_key, watcher_name)

从上面的代码,add_ticket_watcher()是没有返回语句的方法。我从此article了解到,我们可以使用模拟来模仿此方法的预期行为。

对于使用pytest的模拟功能,我发现我们可以使用monkeypatch

所以,我的方法是对add_ticket_watcher()执行2个测试用例:

  • 测试有效票证密钥
  • 测试无效的票证密钥

我有类似的东西:

# test_app.py
import pytest
from src.app import App


@pytest.fixture
def app():
    app = App()
    return app


# Positive test case: Setup parameterize test for valid ticket key
add_valid_watcher_data = (
    ('func_name', 'ticket_key', 'watcher_name', 'expected_result', 'comment'),
    [
        ('add_ticket_watcher', 'TIC-13527', 'someone', None, 'add watcher at valid ticket key'),
    ]
)


@pytest.mark.parametrize(*add_valid_watcher_data)
def test_add_ticket_watcher(monkeypatch, app, func_name, ticket_key, watcher_name, expected_result, comment):

    def mock_add_ticket_watcher(ticket_key, watcher_name):
        # Since `add_ticket_watcher()` has no return statement, I'm mocking the result as None
        return None

    monkeypatch.setattr(app, "add_ticket_watcher", mock_add_ticket_watcher)

    # Run each input parameter from add_valid_watcher_data to `add_ticket_watcher()`
    watcher = getattr(app, func_name)(ticket_key, watcher_name)

    # If watcher has None value, then `add_ticket_watcher()` execution is successful.
    assert expected_result == watcher


# Negative test case: Setup parameterize test for invalid ticket key
add_invalid_watcher_data = (
    ('func_name', 'ticket_key', 'watcher_name', 'exception_message', 'comment'),
    [
        ('add_ticket_watcher', 'TIC-xx', 'someone', 'Ticket key is empty', 'add watcher at invalid ticket key'),
        ('add_ticket_watcher', None, 'someone', 'Ticket key is empty', 'ticket key has None value'),
    ]
)


@pytest.mark.parametrize(*add_invalid_watcher_data)
def test_exception_add_ticket_watcher(app, func_name, ticket_key, watcher_name, exception_message, comment):
    with pytest.raises(ValueError, match=exception_message):
      # Run each input parameter from add_invalid_watcher_data to `add_ticket_watcher()`
      getattr(app, func_name)(ticket_key, watcher_name)

test_add_ticket_watcher()中,我不确定要断言什么。但是,由于App.add_ticket_watcher(ticket_key, watcher_name)没有return语句。我创建了一个模拟函数以返回None

是否有更好的方法可以达到相同的目的?

如何在Pytest中为没有return语句的方法创建单元测试?

python python-3.x unit-testing pytest monkeypatching
2个回答
0
投票
除了chepner提到的内容。您可以测试是否使用模拟调用logger.info。并且为了测试负面情况,您可以使用模拟side_effects强制它引发异常,然后可以测试是否调用了logger.exception。

0
投票
我对pytest不熟悉,但对unittest不熟悉。但是,我将为您的函数编写这3个测试(对现有函数进行一些修改:))

注:测试方法名称具有描述性,因此,我没有添加其他注释。

app.py

from utils import DBConnection import cx_Oracle class App: def add_ticket_watcher(self, ticket_key, watcher_name): if ticket_key is None: raise ValueError('Ticket key is empty') instance = DBConnection() try: instance.save(ticket_key, watcher_name) except Exception as e: raise cx_Oracle.DatabaseError('Database save failed')

test_app.py

import unittest import app import cx_Oracle from mock import patch class TestApp(unittest.TestCase): @classmethod def setUpClass(cls): cls.app = app.App() def test_if_exception_raised_when_ticket_value_is_none(self): with self.assertRaises(ValueError): self.app.add_ticket_watcher(None, 'dummyname') def test_if_dbconnection_save_is_called(self): with patch('app.DBConnection.save') as mock_dbconn_save: self.app.add_ticket_watcher(123, 'dummyname') self.assertTrue(mock_dbconn_save.called) def test_if_dbconnection_save_raises_error(self): with patch('app.DBConnection.save', side_effect = Exception) as mock_dbconn_save_exc: with self.assertRaises(cx_Oracle.DatabaseError): self.app.add_ticket_watcher(123, 'dummyname') if __name__ == '__main__': unittest.main(verbosity=2)

© www.soinside.com 2019 - 2024. All rights reserved.