Bird
Raised Fist0
PyTesttesting~15 mins

Test discovery rules in PyTest - Build an Automation Script

Choose your learning style10 modes available
Verify pytest discovers test files and test functions correctly
Preconditions (2)
Step 1: Create a Python file named test_sample.py with two test functions: test_addition and test_subtraction
Step 2: Create another Python file named sample_test.py with one test function: test_multiplication
Step 3: Create a Python file named sample.py with one function named test_division (not a test file)
Step 4: Run pytest from the project root folder without any arguments
Step 5: Observe which tests pytest discovers and runs
✅ Expected Result: pytest discovers and runs test_addition and test_subtraction from test_sample.py and test_multiplication from sample_test.py. It does not run test_division from sample.py because the file name does not match pytest discovery rules.
Automation Requirements - pytest
Assertions Needed:
Verify that pytest collects exactly three tests
Verify that the test functions test_addition, test_subtraction, and test_multiplication are run
Verify that test_division is not collected or run
Best Practices:
Use pytest's built-in test discovery without custom arguments
Name test files and test functions following pytest conventions (test_*.py or *_test.py for files, test_* for functions)
Use assert statements for validation
Keep test functions independent and simple
Automated Solution
PyTest
import pytest
import os
import subprocess
import sys

def write_file(filename: str, content: str):
    with open(filename, 'w') as f:
        f.write(content)

def test_pytest_discovery(tmp_path):
    # Create test_sample.py with two test functions
    test_sample_content = '''
def test_addition():
    assert 1 + 1 == 2

def test_subtraction():
    assert 2 - 1 == 1
'''
    write_file(tmp_path / 'test_sample.py', test_sample_content)

    # Create sample_test.py with one test function
    sample_test_content = '''
def test_multiplication():
    assert 2 * 3 == 6
'''
    write_file(tmp_path / 'sample_test.py', sample_test_content)

    # Create sample.py with a function named test_division (not a test file)
    sample_content = '''
def test_division():
    assert 6 / 2 == 3
'''
    write_file(tmp_path / 'sample.py', sample_content)

    # Run pytest in the tmp_path directory
    result = subprocess.run(
        [sys.executable, '-m', 'pytest', '--collect-only', '-q'],
        cwd=tmp_path,
        capture_output=True,
        text=True
    )

    # The output lists collected tests by their node ids
    collected_tests = result.stdout.strip().split('\n')

    # We expect exactly 3 tests collected
    assert len(collected_tests) == 3, f"Expected 3 tests collected, got {len(collected_tests)}"

    # Check that the collected tests are the expected ones
    expected_tests = {
        'test_sample.py::test_addition',
        'test_sample.py::test_subtraction',
        'sample_test.py::test_multiplication'
    }

    assert set(collected_tests) == expected_tests, f"Collected tests do not match expected. Got: {collected_tests}"

    # Run pytest normally and capture output
    run_result = subprocess.run(
        [sys.executable, '-m', 'pytest', '-q', '--tb=no'],
        cwd=tmp_path,
        capture_output=True,
        text=True
    )

    # Check that the output contains the names of the three tests run
    for test_name in ['test_addition', 'test_subtraction', 'test_multiplication']:
        assert test_name in run_result.stdout, f"{test_name} not found in pytest output"

    # Check that test_division is not run
    assert 'test_division' not in run_result.stdout, "test_division should not be run because file name does not match discovery rules"

This test script uses pytest and Python's subprocess module to verify pytest's test discovery rules.

First, it creates three Python files in a temporary directory:

  • test_sample.py with two test functions.
  • sample_test.py with one test function.
  • sample.py with a function named like a test but in a non-test file.

Then, it runs pytest --collect-only to list all discovered tests and asserts that only the three functions in the correctly named test files are collected.

Next, it runs pytest normally to execute the tests and checks the output to confirm the expected tests ran and the function in sample.py did not run.

This approach ensures the test discovery rules are correctly followed by pytest.

Common Mistakes - 4 Pitfalls
{'mistake': "Naming test files without the 'test_' prefix or '_test' suffix", 'why_bad': "pytest will not discover test files that do not follow naming conventions, so tests inside those files won't run.", 'correct_approach': "Always name test files starting with 'test_' or ending with '_test.py' to ensure pytest discovers them."}
{'mistake': "Naming test functions without the 'test_' prefix", 'why_bad': "pytest only recognizes functions starting with 'test_' as test functions, so others are ignored.", 'correct_approach': "Prefix all test function names with 'test_' so pytest can find and run them."}
Running pytest with custom arguments that override discovery without understanding them
{'mistake': 'Hardcoding test paths or test names in automation scripts', 'why_bad': 'This reduces flexibility and makes tests brittle if file names or structure change.', 'correct_approach': "Use pytest's discovery features and relative paths to keep tests maintainable."}
Bonus Challenge

Now add data-driven testing with 3 different inputs to one of the test functions using pytest parametrize

Show Hint

Practice

(1/5)
1. Which of the following file names will pytest recognize as a test file by default?
easy
A. example.py
B. test_example.py
C. example_test.pyc
D. TestExample.py

Solution

  1. Step 1: Understand pytest file naming rules

    pytest looks for files starting or ending with 'test' and ending with '.py'.
  2. Step 2: Check each option

    'test_example.py' starts with 'test' and ends with '.py', so pytest will find it. Others either don't end with '.py' or don't start/end with 'test'.
  3. Final Answer:

    test_example.py -> Option B
  4. Quick Check:

    File starts or ends with 'test' + '.py' = test_example.py [OK]
Hint: Test files start or end with 'test' and end with '.py' [OK]
Common Mistakes:
  • Thinking pytest finds .pyc files
  • Ignoring case sensitivity in file names
  • Assuming any .py file is a test file
2. Which function name will pytest recognize as a test function by default?
easy
A. test_login()
B. testLogin()
C. check_login()
D. login_test()

Solution

  1. Step 1: Recall pytest test function naming

    pytest looks for functions starting with 'test_'.
  2. Step 2: Evaluate each function name

    'test_login()' starts with 'test_' exactly, so pytest will find it. Others do not follow this pattern.
  3. Final Answer:

    test_login() -> Option A
  4. Quick Check:

    Function starts with 'test_' = test_login() [OK]
Hint: Test functions start with 'test_' exactly [OK]
Common Mistakes:
  • Using camelCase instead of snake_case
  • Placing 'test' at the end of function name
  • Missing underscore after 'test'
3. Given the following files and functions, which tests will pytest discover and run?
File: test_math.py
  def test_add(): pass
  def add_test(): pass

File: math_test.py
  def test_subtract(): pass
  def subtract_test(): pass

File: math.py
  def test_multiply(): pass
medium
A. test_add, test_subtract
B. test_add, test_subtract, test_multiply
C. test_add, subtract_test
D. add_test, subtract_test

Solution

  1. Step 1: Identify test files pytest finds

    pytest finds files starting or ending with 'test' and ending with '.py'. So 'test_math.py' and 'math_test.py' are test files. 'math.py' is not.
  2. Step 2: Identify test functions pytest finds in those files

    In 'test_math.py', pytest finds 'test_add' (starts with 'test_'). 'add_test' is ignored. In 'math_test.py', pytest finds 'test_subtract'. 'subtract_test' is ignored. 'test_multiply' in 'math.py' is ignored because file is not a test file.
  3. Final Answer:

    test_add, test_subtract -> Option A
  4. Quick Check:

    Files and functions follow naming rules = test_add, test_subtract [OK]
Hint: Test files and functions must follow naming rules to be discovered [OK]
Common Mistakes:
  • Assuming any function starting with 'test' is found regardless of file name
  • Including functions in non-test files
  • Confusing function name endings with beginnings
4. You have a test file named TestExample.py with a function def test_func():. pytest does not run this test. What is the likely cause?
medium
A. Function name does not start with 'test_'
B. pytest requires test classes to run tests
C. File name does not follow pytest discovery rules
D. Function is missing a return statement

Solution

  1. Step 1: Check pytest file discovery rules

    pytest finds files starting or ending with 'test' in lowercase and ending with '.py'. 'TestExample.py' starts with uppercase 'T', so it is not recognized.
  2. Step 2: Verify function name and other options

    Function name 'test_func' is correct. Return statement is not required. pytest does not require test classes to run functions.
  3. Final Answer:

    File name does not follow pytest discovery rules -> Option C
  4. Quick Check:

    File name case-sensitive for discovery = D [OK]
Hint: File names must be lowercase starting or ending with 'test' [OK]
Common Mistakes:
  • Ignoring case sensitivity in file names
  • Thinking function needs return statement
  • Assuming test classes are mandatory
5. You want pytest to discover tests in a file named mytests.py containing functions def test_one(): and def test_two():. By default, pytest does not find this file. How can you rename the file to follow pytest discovery rules without changing function names?
hard
A. Rename to my_test_s.py
B. Rename to mytestsTest.py
C. Rename to testmytests.py
D. Rename to test_mytests.py

Solution

  1. Step 1: Recall pytest file discovery naming

    pytest finds files starting with 'test_' or ending with '_test.py'.
  2. Step 2: Check options for correct naming

    'test_mytests.py' starts with 'test_' [check]. 'mytestsTest.py' ends with 'Test.py' (uppercase 'T' not matching lowercase 'test'). 'testmytests.py' lacks '_' after 'test'. 'my_test_s.py' does not start with 'test_' or end with '_test.py'. Only the first option works.
  3. Final Answer:

    Rename to test_mytests.py -> Option D
  4. Quick Check:

    File starts or ends with 'test' = test_mytests.py [OK]
Hint: File must start or end with 'test' exactly [OK]
Common Mistakes:
  • Removing 'test' from file name
  • Adding 'test' inside word without underscore
  • Using camelCase instead of snake_case
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard