Skip to content

Use pytest Fixtures for Creating Test Objects

Overview

If a test needs one or more objects, provide them via pytest fixtures.

Do not run multiple invokes of typer.testing.CliRunner in one test.

Example

Fixture:

@pytest.fixture()
def create_basic_talk():
    return talk_crud().create({"short_name": "error-messages"})

Test function:

def test_existing_by_id(create_basic_talk):
    result = runner.invoke(app, ["talk", "view", str(create_basic_talk.id_)])

    assert result.exit_code == 0
    assert result.stdout

This provides a clear separation between the different phases of the test:

  • arrange
  • act
  • assert

Pitfall

Another possibility would be to invoke the create command in the test before invoking the "command under test" view.

def test_existing_by_id(create_basic_talk):
    runner.invoke(app, ["talk", "create", "--short-name", "some-name"]

    result = runner.invoke(app, ["talk", "view", str(create_basic_talk.id_)])

    assert result.exit_code == 0
    assert result.stdout

Drawback: If the create command fails, the invoke is still successful and proceeds to the next step.

=>

The invoking of the view command will fail, which is misleading. (The create command has an error, but the test fails in the view step.)

More Info