Skip to content

Pytest missing assert inspection

This inspection reports pytest tests that never assert anything, and tests that explicitly return a value instead of asserting. Both cases silently pass in pytest, so the test looks green while it verifies nothing.

How to use it

Enable the inspection under Settings | BetterPy | Testing (Pytest) | Code Inspections. BetterPy highlights the test name of a test without assertions, and the return <value> statement of a test that returns a value.

def test_user_is_created():
    user = create_user("Alice")
    print(user.name)  # Pytest test has no assert statement

def test_user_name():
    user = create_user("Alice")
    assert user.name == "Alice"
    return user  # Pytest test should not return a value
def test_user_is_created():
    user = create_user("Alice")
    assert user is not None

def test_user_name():
    user = create_user("Alice")
    assert user.name == "Alice"

What counts as an assertion

BetterPy does not just look for a literal assert in the test body. A test is considered to assert something when it:

  • contains a Python assert statement,
  • raises AssertionError explicitly, for example raise AssertionError("unexpected value"),
  • uses pytest.raises(...), pytest.warns(...), or pytest.deprecated_call(), whether as a context manager or as a direct call such as the legacy pytest.raises(ValueError, func, *args) form,
  • calls pytest.fail(...), pytest.xfail(...), or pytest.skip(...) as the terminating check,
  • calls a unittest.TestCase-style assertion on self or cls, such as self.assertEqual(...), self.assertTrue(...), or self.assertRaises(...),
  • calls a fluent assertion helper such as assert_that(...) from assertpy or PyHamcrest,
  • calls a mock assertion method such as assert_called_once_with(...) or assert_not_awaited() on a value BetterPy recognises as a Mock or AsyncMock,
  • or calls a project helper function that itself asserts. Helper chains are followed across files in your own code, up to a bounded depth, and recursive helpers are handled without hanging.

All pytest forms are recognised through the same alias-aware resolution, so import pytest, import pytest as pt, from pytest import warns, and from pytest import raises as expect_error all work.

What is deliberately not reported

  • Functions that pytest would not collect: test-named functions in non-test files, methods in classes that are not test classes, and helper functions or fixtures that happen to start with test_. BetterPy honours python_files, python_classes, python_functions, and testpaths from your pytest configuration.
  • A bare return without a value, and return statements inside nested functions.
  • Assertions inside a nested function that is never called — those do not satisfy the inspection, so such a test is still reported.
  • assert_-prefixed methods on ordinary objects, on Mock(spec=...) where the spec class defines the method, or on Mock(unsafe=True); only real mock assertion methods count. unittest-style assertions are only accepted in their camelCase form (assertEqual, not assert_equal) and only when called on self or cls.
  • Calls that cannot be resolved, for example helpers from third-party libraries — the test is reported, because BetterPy cannot see an assertion.

Notes

  • The inspection reports at weak warning level and only runs on your own code, not on library sources.
  • It is gated by the Pytest missing assert inspection setting.