玩命加载中 . . .

pytest hook系列之pytest_collection_finish


Overview

pytest_collection_finishpytest框架中的一个钩子函数,当测试用例收集过程完成时触发。通过使用这个钩子函数,我们可以在收集完成后进行一些统计、记录或报告等操作。本篇文章将详细介绍pytest_collection_finish的使用场景、参数,并通过具体案例展示其应用。

什么是 pytest_collection_finish?

pytest_collection_finish是一个pytest提供的钩子函数,它在所有测试用例收集完毕后立即调用。使用这个钩子,我们可以获取已经收集到的测试用例列表,并对其进行处理或统计。

使用场景

  • 收集统计信息:统计收集到的测试用例的数量和分布情况。

  • 生成报告:在收集完成后生成一个包含所有测试用例的信息报告。

  • 自定义日志记录:记录测试用例的收集过程和结果,用于调试或审计。

参数

def pytest_collection_finish(session):
    # session: 当前 pytest 会话对象,包含配置信息和收集到的测试用例
    pass


    session:当前 pytest 会话对象,包含配置信息和已经收集到的测试用例。

示例代码

案例一:收集统计信息

目标:统计收集到的测试用例的数量和分布情况,并在收集完成后打印统计信息。

步骤:

  • 使用pytest_collection_finish钩子获取收集到的测试用例列表。

  • 统计测试用例的数量和分布情况。

  • 打印统计信息。

示例代码:

# conftest.py
import pytest

def pytest_collection_finish(session):
    total_tests = len(session.items)
    print(f"Total collected tests: {total_tests}")

    # 统计每个文件的测试用例数量
    file_test_count = {}
    for item in session.items:
        file_name = item.fspath
        if file_name not in file_test_count:
            file_test_count[file_name] = 0
        file_test_count[file_name] += 1

    for file_name, count in file_test_count.items():
        print(f"File {file_name}: {count} tests")

# 示例测试文件 `tests/test_example.py`
def test_example1():
    assert 1 + 1 == 2

def test_example2():
    assert 2 + 2 == 4

def test_example3():
    assert 3 + 3 == 6

运行效果:

root@Gavin:~/test/hook# pytest
================================================================================================================== test session starts ==================================================================================================================
platform linux -- Python 3.11.6, pytest-8.0.2, pluggy-1.5.0
Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type>
sensitiveurl: .*
rootdir: /root/test/hook
plugins: cov-4.1.0, order-1.2.0, random-order-1.1.1, tornasync-0.6.0.post2, check-2.2.2, instafail-0.5.0, allure-pytest-2.13.2, asyncio-0.23.6, selenium-4.1.0, xdist-3.5.0, variables-3.1.0, rerunfailures-13.0, html-4.1.1, progress-1.2.5, metadata-3.0.0, twisted-1.14.1, picked-0.5.0, anyio-4.3.0, Faker-24.0.0, trio-0.8.0, repeat-0.9.3, base-url-2.1.0, dependency-0.6.0, dotenv-0.5.2, timeout-2.2.0
asyncio: mode=Mode.STRICT
collected 3 items                                                                                                                                                                                                                                       
Total collected tests: 3
File /root/test/hook/test_example.py: 3 tests

test_example.py ...                                                                                                                                                                                                                               [100%]

=================================================================================================================== 3 passed in 0.04s ===================================================================================================================
root@Gavin:~/test/hook# 

说明:

  • pytest_collection_finish钩子中,通过session.items获取收集到的所有测试用例?

  • 统计每个测试文件中的测试用例数量,并打印结果。

案例二:生成测试用例报告

目标:在收集完成后生成一个包含所有测试用例信息的报告文件。

步骤:

  • 使用pytest_collection_finish钩子获取收集到的测试用例列表。

  • 将测试用例信息写入报告文件。

示例代码:

# conftest.py
import pytest

def pytest_collection_finish(session):
    report_lines = ["Collected test cases:\n"]
    for item in session.items:
        report_lines.append(f"{item.nodeid}\n")

    report_file = "test_collection_report.txt"
    with open(report_file, "w") as f:
        f.writelines(report_lines)
    print(f"Test collection report generated: {report_file}")

# 示例测试文件 `tests/test_example.py`
def test_example1():
    assert 1 + 1 == 2

def test_example2():
    assert 2 + 2 == 4

def test_example3():
    assert 3 + 3 == 6

运行效果:

root@Gavin:~/test/hook# pytest
================================================================================================================== test session starts ==================================================================================================================
platform linux -- Python 3.11.6, pytest-8.0.2, pluggy-1.5.0
Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type>
sensitiveurl: .*
rootdir: /root/test/hook
plugins: cov-4.1.0, order-1.2.0, random-order-1.1.1, tornasync-0.6.0.post2, check-2.2.2, instafail-0.5.0, allure-pytest-2.13.2, asyncio-0.23.6, selenium-4.1.0, xdist-3.5.0, variables-3.1.0, rerunfailures-13.0, html-4.1.1, progress-1.2.5, metadata-3.0.0, twisted-1.14.1, picked-0.5.0, anyio-4.3.0, Faker-24.0.0, trio-0.8.0, repeat-0.9.3, base-url-2.1.0, dependency-0.6.0, dotenv-0.5.2, timeout-2.2.0
asyncio: mode=Mode.STRICT
collected 3 items                                                                                                                                                                                                                                       
Test collection report generated: test_collection_report.txt

test_example.py ...                                                                                                                                                                                                                               [100%]

=================================================================================================================== 3 passed in 0.04s ===================================================================================================================
root@Gavin:~/test/hook# 

说明:

  • pytest_collection_finish钩子中,通过session.items获取所有收集到的测试用例。

  • 将每个测试用例的节点ID写入一个报告文件test_collection_report.txt并生成报告。

案例三:自定义日志记录

目标:在收集完成后记录日志,包含测试用例的收集情况和统计信息。

步骤:

  • 使用pytest_collection_finish钩子获取收集到的测试用例列表。

  • 记录日志文件,包含测试用例的收集信息和统计数据。

示例代码:

# conftest.py
import pytest
import logging

def pytest_sessionstart(session):
    logging.basicConfig(filename='test_collection.log', level=logging.INFO, format='%(asctime)s - %(message)s')
    logging.info("Test session started")

def pytest_collection_finish(session):
    logging.info("Collected test cases:")
    total_tests = len(session.items)
    logging.info(f"Total collected tests: {total_tests}")

    for item in session.items:
        logging.info(f"Collected: {item.nodeid}")

    logging.info("Test collection finished")

# 示例测试文件 `tests/test_example.py`
def test_example1():
    assert 1 + 1 == 2

def test_example2():
    assert 2 + 2 == 4

def test_example3():
    assert 3 + 3 == 6

运行效果:

root@Gavin:~/test/hook# pytest
================================================================================================================== test session starts ==================================================================================================================
platform linux -- Python 3.11.6, pytest-8.0.2, pluggy-1.5.0
Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type>
sensitiveurl: .*
rootdir: /root/test/hook
plugins: cov-4.1.0, order-1.2.0, random-order-1.1.1, tornasync-0.6.0.post2, check-2.2.2, instafail-0.5.0, allure-pytest-2.13.2, asyncio-0.23.6, selenium-4.1.0, xdist-3.5.0, variables-3.1.0, rerunfailures-13.0, html-4.1.1, progress-1.2.5, metadata-3.0.0, twisted-1.14.1, picked-0.5.0, anyio-4.3.0, Faker-24.0.0, trio-0.8.0, repeat-0.9.3, base-url-2.1.0, dependency-0.6.0, dotenv-0.5.2, timeout-2.2.0
asyncio: mode=Mode.STRICT
collected 3 items                                                                                                                                                                                                                                       

test_example.py ...                                                                                                                                                                                                                               [100%]

=================================================================================================================== 3 passed in 0.04s ===================================================================================================================
root@Gavin:~/test/hook# cat test_
test_collection_report.txt  test_example.py             
root@Gavin:~/test/hook# cat test_collection_report.txt 
Collected test cases:
test_example.py::test_example1
test_example.py::test_example2
test_example.py::test_example3
root@Gavin:~/test/hook#

说明:

  • pytest_sessionstart钩子用来配置日志文件,并记录测试会话的开始时间。

  • pytest_collection_finish钩子中记录每个收集到的测试用例的节点ID,以及收集完成的总数和其他信息。

结语

pytest_collection_finish是一个非常有用的pytest钩子,能够在测试用例收集完成后提供多种操作可能。通过本文的案例,你可以了解如何使用pytest_collection_finish来统计信息、生成报告和记录日志。在实际应用中,可以根据项目需求及测试场景对这些示例进行扩展和调整。


文章作者: Gavin Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Gavin Wang !
  目录