CtrlK
BlogDocsLog inGet started
Tessl Logo

golikovichev/pytest-conversational

Test chat bots, voice assistants, and IVR menus with pytest using a small Conversation object and a callable bot adapter. Use when the user wants to write rule-based assertions over multi-turn dialogue without bringing in an LLM dependency, when they have a chatbot reachable as a Python callable or HTTP webhook, when they need to keep per-conversation state across turns and assert on slot filling, when they want pytest-native fixtures and a printable transcript on failure, or when they mention voice-assistant testing, IVR menu testing, conversational AI testing, LLM bot testing (used as the target under test, not as the matcher), expect matchers for bot replies, or multi-turn dialogue tests.

99

1.56x
Quality

100%

Does it follow best practices?

Impact

97%

1.56x

Average score across 3 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

test_plugin_integration.pytests/

"""End-to-end checks that the plugin wires up through entry_points.

Each test runs a fresh inline pytest session via pytester so the assertions
verify what a real user sees after ``pip install pytest-conversational``:
fixtures resolve without an explicit import, and the ``conversational``
marker is registered cleanly under ``--strict-markers``.
"""


def test_conversation_fixture_is_discovered(pytester):
    """The ``conversation`` fixture must be available with zero imports."""
    pytester.makepyfile(
        """
        def test_uses_fixture(conversation):
            assert conversation.turns == []
            conversation.add_user("hello")
            assert conversation.turns[-1].user == "hello"
        """
    )
    result = pytester.runpytest("-q")
    result.assert_outcomes(passed=1)


def test_conversation_factory_fixture_is_discovered(pytester):
    """The ``conversation_factory`` fixture builds adapters on demand."""
    pytester.makepyfile(
        """
        def test_uses_factory(conversation_factory):
            convo = conversation_factory(bot=lambda text, c: f"echo: {text}")
            convo.say("ping")
            assert convo.last.bot == "echo: ping"
        """
    )
    result = pytester.runpytest("-q")
    result.assert_outcomes(passed=1)


def test_conversational_marker_does_not_warn_under_strict(pytester):
    """``@pytest.mark.conversational`` must resolve with no PytestUnknownMarkWarning."""
    pytester.makepyfile(
        """
        import pytest

        @pytest.mark.conversational
        def test_marked(conversation):
            conversation.add_user("hi")
            assert len(conversation.turns) == 1
        """
    )
    result = pytester.runpytest("-q", "--strict-markers", "-W", "error")
    result.assert_outcomes(passed=1)


def test_conversational_marker_filters_collection(pytester):
    """``pytest -m conversational`` selects only marked tests."""
    pytester.makepyfile(
        """
        import pytest

        @pytest.mark.conversational
        def test_picked():
            assert True

        def test_skipped():
            assert True
        """
    )
    result = pytester.runpytest("-q", "-m", "conversational")
    result.assert_outcomes(passed=1, deselected=1)

CHANGELOG.md

CONTRIBUTING.md

README.md

REFERENCE.md

SECURITY.md

SKILL.md

tessl.json

tile.json