Luiz
Luiz

Reputation: 371

Why using yield instead of return in pytest fixtures?

I see why using yield keyword when we want to run our tests and then clean things up going back to the fixture and running some code after the yield statement. As the code below.

@pytest.fixture
def sending_user(mail_admin):
    user = mail_admin.create_user()
    yield user
    mail_admin.delete_user(user)

However why is it necessary to use yield when we only want to return an object and don't comeback to the fixture, returning a patch for example?

from unittest.mock import patch, mock_open
from pytest import raises, fixture
import os.path

def read_from_file(file_path):
    if not os.path.exists(file_path):
        raise Exception("File does not exists!")
    with open(file_path, "r") as f:
        return f.read().splitlines()[0]

@fixture()
def mock_open_file():
    with patch("builtins.open", new_callable=mock_open, read_data="Correct string") as mocked:
        yield mocked #instead of: return mocked

@fixture()
def mock_os():
    with patch("os.path.exists", return_value=True) as mocked:
        yield mocked #instead of: return mocked

def test_read_file_and_returns_the_correct_string_with_one_line(mock_os, mock_open_file):
    result = read_from_file("xyz")
    mock_open_file.assert_called_once_with("xyz", "r")
    assert result == "Correct string"

def test_throws_exception_when_file_doesnt_exist(mock_os, mock_open_file):
    mock_os.return_value = False
    with raises(Exception):
        read_from_file("xyz")

Upvotes: 5

Views: 7477

Answers (1)

Anh Tran
Anh Tran

Reputation: 31

  • In a pytest fixture, we can definitely use return instead of yield keyword if there's nothing after yield statement.
  • The reason you must use yield for the 2 fixtures here is because both of them are contextmanager

Upvotes: 3

Related Questions