From 89aa9f9eb9ddbf9a2e308c8fe11989d0456200ed Mon Sep 17 00:00:00 2001 From: Jorgen Kvalvaag Date: Thu, 14 Nov 2024 12:40:34 +0100 Subject: [PATCH] tests: Add report, restructure Add html report Restructure tests, markers Signed-off-by: Jorgen Kvalvaag --- .github/workflows/on_target.yml | 196 ++++-------------- .github/workflows/test.yml | 72 +------ tests/on_target/requirements.txt | 1 + tests/on_target/tests/conftest.py | 45 +++- tests/on_target/tests/pytest.ini | 1 + .../{ => test_bridge}/test_conn_bridge.py | 15 +- .../{ => test_bridge}/test_serial_dfu.py | 8 +- .../tests/{ => test_functional}/test_fota.py | 18 +- .../{ => test_functional}/test_location.py | 22 +- .../{ => test_functional}/test_traces.py | 5 +- .../{ => test_functional}/test_uart_output.py | 23 +- .../tests/{ => test_ppk}/test_power.py | 8 +- tests/on_target/utils/test_uart.py | 15 ++ 13 files changed, 163 insertions(+), 266 deletions(-) rename tests/on_target/tests/{ => test_bridge}/test_conn_bridge.py (95%) rename tests/on_target/tests/{ => test_bridge}/test_serial_dfu.py (97%) rename tests/on_target/tests/{ => test_functional}/test_fota.py (95%) rename tests/on_target/tests/{ => test_functional}/test_location.py (82%) rename tests/on_target/tests/{ => test_functional}/test_traces.py (97%) rename tests/on_target/tests/{ => test_functional}/test_uart_output.py (74%) rename tests/on_target/tests/{ => test_ppk}/test_power.py (97%) diff --git a/.github/workflows/on_target.yml b/.github/workflows/on_target.yml index 0d1cdb83..ed2d5223 100644 --- a/.github/workflows/on_target.yml +++ b/.github/workflows/on_target.yml @@ -3,44 +3,23 @@ name: Target tests on: workflow_call: inputs: + artifact_run_id: + description: The run ID of the workflow to fetch artifacts from + type: string + required: true artifact_fw_version: + description: The firmware version found under this run_id type: string required: true - artifact_run_id: + pytest_marker: type: string required: true - run_log_check_tests: - type: boolean - required: false - default: true - run_fota_tests: - type: boolean - required: false - default: true - run_fullmfwfota_test: - type: boolean - required: false - default: false - run_dfu_tests: - type: boolean - required: false - default: true - run_connectivity_bridge_tests: - type: boolean - required: false - default: true - run_wifi_location_tests: - type: boolean - required: false - default: true - run_modem_trace_tests: - type: boolean - required: false - default: true - run_ppk_tests: - type: boolean + default: -m "not slow" + pytest_path: + type: string required: false - default: false + default: tests + workflow_dispatch: inputs: artifact_fw_version: @@ -51,38 +30,16 @@ on: description: The run ID of the workflow to fetch artifacts from type: string required: true - run_log_check_tests: - type: boolean - required: true - default: true - run_fota_tests: - type: boolean - required: true - default: false - run_fullmfwfota_test: - type: boolean - required: true - default: false - run_dfu_tests: - type: boolean - required: true - default: false - run_connectivity_bridge_tests: - type: boolean - required: true - default: false - run_wifi_location_tests: - type: boolean - required: true - default: false - run_modem_trace_tests: - type: boolean - required: true - default: false - run_ppk_tests: - type: boolean + pytest_marker: + description: The pytest marker to run + type: string required: true - default: false + default: -m "not slow" + pytest_path: + description: Select test execution path + type: string + required: false + default: tests jobs: target_test: @@ -135,107 +92,27 @@ jobs: --software-version ${{ inputs.artifact_fw_version }} \ hello.nrfcloud.com-${{ inputs.artifact_fw_version }}-thingy91x-nrf91.elf - - name: Run UART tests - if: ${{ inputs.run_log_check_tests }} + - name: Tests working-directory: thingy91x-oob/tests/on_target run: | mkdir -p results - pytest -s -v -m "dut1 and uart" \ - --junit-xml=results/test-results-uart.xml \ - tests - env: - SEGGER: ${{ secrets.SEGGER_DUT_1 }} - LOG_FILENAME: oob_uart_test_log - - - name: Run FOTA tests (standard) - if: ${{ inputs.run_fota_tests }} - working-directory: thingy91x-oob/tests/on_target - run: | - pytest -s -v -m "dut1 and fota" \ - --junit-xml=results/test-results-fota.xml \ - tests - env: - SEGGER: ${{ secrets.SEGGER_DUT_1 }} - IMEI: ${{ secrets.IMEI_DUT_1 }} - FINGERPRINT: ${{ secrets.FINGERPRINT_DUT_1 }} - LOG_FILENAME: oob_fota_test_log - - - name: Run FOTA tests (FULLMFW) - if: ${{ inputs.run_fullmfwfota_test }} - working-directory: thingy91x-oob/tests/on_target - run: | - pytest -s -v -m "dut1 and fullmfw_fota" \ - --junit-xml=results/test-results-fullmfw-fota.xml \ - tests + pytest -s -v ${{ inputs.pytest_marker }} \ + --junit-xml=results/test-results-dut1.xml \ + --html=results/test-results-dut1.html --self-contained-html \ + ${{ inputs.pytest_path }} env: SEGGER: ${{ secrets.SEGGER_DUT_1 }} - IMEI: ${{ secrets.IMEI_DUT_1 }} - FINGERPRINT: ${{ secrets.FINGERPRINT_DUT_1 }} - LOG_FILENAME: oob_fullmfw_fota_test_log - - - name: Run DFU tests - if: ${{ inputs.run_dfu_tests }} - working-directory: thingy91x-oob/tests/on_target - run: | - pytest -s -v -m "dut2 and dfu" \ - --junit-xml=results/test-results-dfu.xml \ - tests - env: SEGGER_NRF53: ${{ secrets.SEGGER_DUT_2_EXT_DBG }} SEGGER_NRF91: ${{ secrets.SEGGER_DUT_2_NRF91 }} - UART_ID: ${{ secrets.UART_DUT_2 }} - - LOG_FILENAME: oob_dfu_test_log - - - name: Run Connectivity Bridge Test - if: ${{ inputs.run_connectivity_bridge_tests }} - working-directory: thingy91x-oob/tests/on_target - run: | - pytest -s -v -m "dut2 and conn_bridge" \ - --junit-xml=results/test-results-connectivity-bridge.xml \ - tests - env: - SEGGER_NRF53: ${{ secrets.SEGGER_DUT_2_EXT_DBG }} - UART_ID: ${{ secrets.UART_DUT_2 }} - LOG_FILENAME: oob_conn_bridge_test_log - - - name: Run Wi-Fi location tests - if: ${{ inputs.run_wifi_location_tests }} - working-directory: thingy91x-oob/tests/on_target - run: | - mkdir -p results - pytest -s -v -m "dut1 and wifi" \ - --junit-xml=results/test-results-wifi-location.xml \ - tests - env: - SEGGER: ${{ secrets.SEGGER_DUT_1 }} - - - name: Run modem trace test - if: ${{ inputs.run_modem_trace_tests }} - working-directory: thingy91x-oob/tests/on_target - run: | - mkdir -p results - pytest -s -v -m "dut1 and traces" \ - --junit-xml=results/test-results-traces-location.xml \ - tests - env: - SEGGER: ${{ secrets.SEGGER_DUT_1 }} - - - name: Run PPK tests - if: ${{ inputs.run_ppk_tests }} - continue-on-error: true - id: ppk_test - working-directory: thingy91x-oob/tests/on_target - run: | - mkdir -p results - pytest -s -v -m dut_ppk \ - --junit-xml=results/test-results-ppk.xml \ - tests - env: - SEGGER: ${{ secrets.SEGGER_DUT_PPK }} + IMEI: ${{ secrets.IMEI_DUT_1 }} + UART_ID_DUT_2: ${{ secrets.UART_DUT_2 }} + FINGERPRINT: ${{ secrets.FINGERPRINT_DUT_1 }} + LOG_FILENAME: oob_uart_test_log + TEST_REPORT_NAME: OOB Firwmare Test Report + DUT1_HW_REVISION: ${{ vars.DUT1_HW_REVISION }} + SEGGER_PPK: ${{ secrets.SEGGER_DUT_PPK }} - name: Commit and Push Badge File to gh-pages Branch - if: ${{ inputs.run_ppk_tests }} continue-on-error: true working-directory: thingy91x-oob env: @@ -251,6 +128,15 @@ jobs: fail-on-empty: true title: OOB FW Test Results + - name: Create Report Artifact + if: always() + uses: actions/upload-artifact@v4 + id: artifact-report + with: + name: test-report + path: | + thingy91x-oob/tests/on_target/results/*.html + - name: Push log files to artifacts if: always() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d57ef48..dbac4fa6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,34 +3,11 @@ name: Build and Test on: workflow_dispatch: inputs: - run_fota_tests: - type: boolean + pytest_marker: + type: string required: true - default: true - run_fullmfwfota_test: - type: boolean - required: true - default: false - run_dfu_tests: - type: boolean - required: true - default: true - run_connectivity_bridge_tests: - type: boolean - required: true - default: true - run_wifi_location_tests: - type: boolean - required: true - default: true - run_modem_trace_tests: - type: boolean - required: true - default: true - run_ppk_tests: - type: boolean - required: true - default: false + default: -m "not slow" + schedule: - cron: "0 0 * * *" push: @@ -58,43 +35,4 @@ jobs: with: artifact_fw_version: ${{ needs.build.outputs.version }} artifact_run_id: ${{ needs.build.outputs.run_id }} - run_fota_tests: >- - ${{ - github.event_name == 'schedule' || - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_fota_tests == 'true') - }} - run_fullmfwfota_test: >- - ${{ - github.event_name == 'schedule' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_fullmfwfota_test == 'true') - }} - run_dfu_tests: >- - ${{ - github.event_name == 'schedule' || - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_dfu_tests == 'true') - }} - run_connectivity_bridge_tests: >- - ${{ - github.event_name == 'schedule' || - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_connectivity_bridge_tests == 'true') - }} - run_wifi_location_tests: >- - ${{ - github.event_name == 'schedule' || - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_wifi_location_tests == 'true') - }} - run_modem_trace_tests: >- - ${{ - github.event_name == 'schedule' || - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_modem_trace_tests == 'true') - }} - run_ppk_tests: >- - ${{ - github.event_name == 'schedule' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.run_ppk_tests == 'true') - }} + pytest_marker: ${{ github.event.inputs.pytest_marker || '' }} diff --git a/tests/on_target/requirements.txt b/tests/on_target/requirements.txt index 8351c6fa..4b331be2 100644 --- a/tests/on_target/requirements.txt +++ b/tests/on_target/requirements.txt @@ -1,4 +1,5 @@ pytest +pytest-html pyserial termcolor pyusb diff --git a/tests/on_target/tests/conftest.py b/tests/on_target/tests/conftest.py index 48f52536..e917d287 100644 --- a/tests/on_target/tests/conftest.py +++ b/tests/on_target/tests/conftest.py @@ -5,13 +5,13 @@ import os import re -import pytest import types +import pytest +import subprocess +from pytest_metadata.plugin import metadata_key from utils.flash_tools import recover_device from utils.uart import Uart, UartBinary from utils.hellonrfcloud_fota import HelloNrfCloudFOTA -import sys -sys.path.append(os.getcwd()) from utils.logger import get_logger logger = get_logger() @@ -19,10 +19,45 @@ UART_TIMEOUT = 60 * 30 SEGGER = os.getenv('SEGGER') -UART_ID = os.getenv('UART_ID', SEGGER) +UART_ID = SEGGER FOTADEVICE_IMEI = os.getenv('IMEI') FOTADEVICE_FINGERPRINT = os.getenv('FINGERPRINT') +def pytest_html_report_title(report): + report.title = os.getenv("TEST_REPORT_NAME", "OOB Test Report") + + +def check_output(cmd, regexp): + p = subprocess.check_output(cmd.split()).decode().strip() + match = re.search(regexp, p) + return match.group(1) + +def pytest_configure(config): + config.stash[metadata_key]["Board"] = "thingy91x" + config.stash[metadata_key]["Board revision"] = os.getenv("DUT1_HW_REVISION", "Undefined") + config.stash[metadata_key]["nrfutil version"] = check_output("nrfutil --version", r"nrfutil ([0-9\.]+)") + config.stash[metadata_key]["nrfutil-device version"] = check_output( + "nrfutil device --version", + r"nrfutil-device ([0-9\.]+)" + ) + config.stash[metadata_key]["SEGGER JLink version"] = check_output( + "nrfutil device --version", + r"SEGGER J-Link version: JLink_V([0-9a-z\.]+)" + ) + +# Add column to table for test specification +def pytest_html_results_table_header(cells): + cells.insert(2, "Specification") + +def pytest_html_results_table_row(report, cells): + cells.insert(2, f"{report.description}") + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_makereport(item, call): + outcome = yield + report = outcome.get_result() + report.description = str(item.function.__doc__) + def get_uarts(): base_path = "/dev/serial/by-id" try: @@ -61,7 +96,7 @@ def t91x_board(): log_uart_string = all_uarts[0] uart = Uart(log_uart_string, timeout=UART_TIMEOUT) fota = HelloNrfCloudFOTA(device_id=f"oob-{FOTADEVICE_IMEI}", \ - fingerprint=FOTADEVICE_FINGERPRINT) + fingerprint=FOTADEVICE_FINGERPRINT) yield types.SimpleNamespace( uart=uart, diff --git a/tests/on_target/tests/pytest.ini b/tests/on_target/tests/pytest.ini index 8ecdf2af..2276aa22 100644 --- a/tests/on_target/tests/pytest.ini +++ b/tests/on_target/tests/pytest.ini @@ -1,5 +1,6 @@ [pytest] markers = + slow: marks tests as slow (deselect with '-m "not slow"') dut1: device used for uart and fota tests dut2: device used for dfu tests uart: uart tests diff --git a/tests/on_target/tests/test_conn_bridge.py b/tests/on_target/tests/test_bridge/test_conn_bridge.py similarity index 95% rename from tests/on_target/tests/test_conn_bridge.py rename to tests/on_target/tests/test_bridge/test_conn_bridge.py index 7d432213..b56471a9 100644 --- a/tests/on_target/tests/test_conn_bridge.py +++ b/tests/on_target/tests/test_bridge/test_conn_bridge.py @@ -29,7 +29,7 @@ SEGGER_NRF53 = os.getenv('SEGGER_NRF53') SEGGER_NRF91 = os.getenv('SEGGER_NRF91') -CONNECTIVITY_BRIDGE_UART = "THINGY91X_" + os.getenv('UART_ID', "") +CONNECTIVITY_BRIDGE_UART = "THINGY91X_" + os.getenv('UART_ID_DUT_2', "") @@ -74,10 +74,17 @@ def t91x_conn_bridge(): uart0.stop() uart1.stop() - -@pytest.mark.dut2 -@pytest.mark.conn_bridge +@pytest.mark.slow def test_conn_bridge(t91x_conn_bridge): + ''' + Test the connectivity bridge between nRF53 and nRF91 + + Test steps: + 1. Wait for UART0 and UART1 to be available + 2. Send 4k of data from USB to UART0 + 3. Send 4k of data from UART1 to USB + 4. Send 40k of data from UART1 to USB + ''' t91x_conn_bridge.uart0.wait_for_str( "UART0 running at baudrate 115200", timeout=UART_TIMEOUT ) diff --git a/tests/on_target/tests/test_serial_dfu.py b/tests/on_target/tests/test_bridge/test_serial_dfu.py similarity index 97% rename from tests/on_target/tests/test_serial_dfu.py rename to tests/on_target/tests/test_bridge/test_serial_dfu.py index 5aa690e9..1bb8a74c 100644 --- a/tests/on_target/tests/test_serial_dfu.py +++ b/tests/on_target/tests/test_bridge/test_serial_dfu.py @@ -26,7 +26,7 @@ SEGGER_NRF53 = os.getenv('SEGGER_NRF53') SEGGER_NRF91 = os.getenv('SEGGER_NRF91') -CONNECTIVITY_BRIDGE_UART = "THINGY91X_" + os.getenv('UART_ID', "") +CONNECTIVITY_BRIDGE_UART = "THINGY91X_" + os.getenv('UART_ID_DUT_2', "") @pytest.fixture(scope="function") def t91x_dfu(): @@ -73,9 +73,11 @@ def t91x_dfu(): uart.stop() -@pytest.mark.dut2 -@pytest.mark.dfu +@pytest.mark.slow def test_dfu(t91x_dfu): + ''' + Test to perform DFU on nRF53 + ''' logger.info("Starting DFU, stopping UART") t91x_dfu.uart.stop() diff --git a/tests/on_target/tests/test_fota.py b/tests/on_target/tests/test_functional/test_fota.py similarity index 95% rename from tests/on_target/tests/test_fota.py rename to tests/on_target/tests/test_functional/test_fota.py index 7577e390..0f59322a 100644 --- a/tests/on_target/tests/test_fota.py +++ b/tests/on_target/tests/test_functional/test_fota.py @@ -74,10 +74,10 @@ def _run_fota(bundleId, fota_type, fotatimeout=APP_FOTA_TIMEOUT, test_fota_resum return _run_fota - -@pytest.mark.dut1 -@pytest.mark.fota def test_app_fota(t91x_board, hex_file, run_fota_fixture): + ''' + Test application FOTA on nrf9151 + ''' # Get latest APP fota bundle results = t91x_board.fota.get_fota_bundles() if not results: @@ -94,9 +94,10 @@ def test_app_fota(t91x_board, hex_file, run_fota_fixture): run_fota_fixture(bundleId=latest_app_bundle["bundleId"], fota_type="app", test_fota_resumption=True) -@pytest.mark.dut1 -@pytest.mark.fota def test_delta_mfw_fota(t91x_board, hex_file, run_fota_fixture): + ''' + Test delta modem FOTA on nrf9151 + ''' # Flash with mfw201 flash_device(os.path.abspath(MFW_201_FILEPATH)) @@ -106,8 +107,9 @@ def test_delta_mfw_fota(t91x_board, hex_file, run_fota_fixture): # Restore mfw201 flash_device(os.path.abspath(MFW_201_FILEPATH)) - -@pytest.mark.dut1 -@pytest.mark.fullmfw_fota +@pytest.mark.slow def test_full_mfw_fota(t91x_board, hex_file, run_fota_fixture): + ''' + Test full modem FOTA on nrf9151 + ''' run_fota_fixture(FULL_MFW_BUNDLEID, "full", FULL_MFW_FOTA_TIMEOUT) diff --git a/tests/on_target/tests/test_location.py b/tests/on_target/tests/test_functional/test_location.py similarity index 82% rename from tests/on_target/tests/test_location.py rename to tests/on_target/tests/test_functional/test_location.py index 82d563b5..46a09fd7 100644 --- a/tests/on_target/tests/test_location.py +++ b/tests/on_target/tests/test_functional/test_location.py @@ -3,37 +3,41 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause ########################################################################################## -import pytest -import time import os from utils.flash_tools import flash_device, reset_device import sys +import pytest +from utils.flash_tools import flash_device, reset_device + sys.path.append(os.getcwd()) from utils.logger import get_logger logger = get_logger() -@pytest.mark.wifi -@pytest.mark.dut1 def test_wifi_location(t91x_board, hex_file): + ''' + Test that the device can get location using Wi-Fi + ''' run_location(t91x_board, hex_file, location_method="Wi-Fi") -@pytest.mark.gnss def test_gnss_location(t91x_board, hex_file): + ''' + Test that the device can get location using GNSS + ''' run_location(t91x_board, hex_file, location_method="GNSS") def run_location(t91x_board, hex_file, location_method): flash_device(os.path.abspath(hex_file)) t91x_board.uart.xfactoryreset() patterns_cloud_connection = [ - "Network connectivity established", - "Connected to Cloud" + "Network connectivity established", + "Connected to Cloud" ] patterns_location = ["Wi-Fi and cellular methods combined"] if location_method == "Wi-Fi" else [] patterns_location = patterns_location + [ - "location_event_handler: Got location: lat:", - "Location search done"] + "location_event_handler: Got location: lat:", + "Location search done"] # Cloud connection t91x_board.uart.flush() diff --git a/tests/on_target/tests/test_traces.py b/tests/on_target/tests/test_functional/test_traces.py similarity index 97% rename from tests/on_target/tests/test_traces.py rename to tests/on_target/tests/test_functional/test_traces.py index 3fcf61a3..88fe99b1 100644 --- a/tests/on_target/tests/test_traces.py +++ b/tests/on_target/tests/test_functional/test_traces.py @@ -17,9 +17,10 @@ trace_read_timeout = 60 threshold_lost_traces = 200 -@pytest.mark.traces -@pytest.mark.dut1 def test_traces(t91x_traces, hex_file): + ''' + Test that the device can collect and dump modem traces to uart1 + ''' flash_device(os.path.abspath(hex_file)) time.sleep(5) t91x_traces.uart.xfactoryreset() diff --git a/tests/on_target/tests/test_uart_output.py b/tests/on_target/tests/test_functional/test_uart_output.py similarity index 74% rename from tests/on_target/tests/test_uart_output.py rename to tests/on_target/tests/test_functional/test_uart_output.py index 0a70df0f..3632ce04 100644 --- a/tests/on_target/tests/test_uart_output.py +++ b/tests/on_target/tests/test_functional/test_uart_output.py @@ -14,29 +14,30 @@ logger = get_logger() -@pytest.mark.dut1 -@pytest.mark.uart def test_uart_output(t91x_board, hex_file): + ''' + Test that the device is operating normally by checking UART output + ''' flash_device(os.path.abspath(hex_file)) t91x_board.uart.xfactoryreset() patterns_boot = [ - "Network connectivity established", - "Connected to Cloud", - "trigger: frequent_poll_entry: frequent_poll_entry", - "trigger: trigger_work_fn: Sending data sample trigger", - "environmental_module: sample: temp:", - "transport: state_connected_ready_run: Payload", - "Location search done" + "Network connectivity established", + "Connected to Cloud", + "trigger: frequent_poll_entry: frequent_poll_entry", + "trigger: trigger_work_fn: Sending data sample trigger", + "environmental_module: sample: temp:", + "transport: state_connected_ready_run: Payload", + "Location search done" ] patterns_button_press = [ "trigger: frequent_poll_run: Button 1 pressed in frequent poll state, restarting duration timer", "trigger_poll_work_fn: Sending shadow/fota poll trigger" ] patterns_lte_offline = [ - "network: Network connectivity lost", + "network: Network connectivity lost", ] patterns_lte_normal = [ - "network: Network connectivity established", + "network: Network connectivity established", ] # Boot diff --git a/tests/on_target/tests/test_power.py b/tests/on_target/tests/test_ppk/test_power.py similarity index 97% rename from tests/on_target/tests/test_power.py rename to tests/on_target/tests/test_ppk/test_power.py index face2f47..d2303909 100644 --- a/tests/on_target/tests/test_power.py +++ b/tests/on_target/tests/test_ppk/test_power.py @@ -158,9 +158,13 @@ def thingy91x_ppk2(): recover_device() ppk2_dev.stop_measuring() - -@pytest.mark.dut_ppk +@pytest.mark.slow def test_power(thingy91x_ppk2, hex_file): + ''' + Test that the device can reach PSM and measure the current consumption + + Current consumption is measured and report generated. + ''' flash_device(os.path.abspath(hex_file)) reset_device() try: diff --git a/tests/on_target/utils/test_uart.py b/tests/on_target/utils/test_uart.py index 5cadb9bb..c32380f4 100644 --- a/tests/on_target/utils/test_uart.py +++ b/tests/on_target/utils/test_uart.py @@ -27,6 +27,7 @@ def mocked_uart(uart_init): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_1(time_sleep, time_time): + """Test that wait_for_str() works for list""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" u.wait_for_str(["foo", "bar", "baz"]) @@ -34,6 +35,7 @@ def test_wait_1(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_2_out_of_order(time_sleep, time_time): + """Test that wait_for_str() works for out of order list""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" u.wait_for_str(["baz", "foo", "bar"], timeout=3) @@ -41,6 +43,7 @@ def test_wait_2_out_of_order(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_3_missing(time_sleep, time_time): + """Test that wait_for_str() asserts when string is missing""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" with pytest.raises(AssertionError) as ex_info: @@ -50,6 +53,7 @@ def test_wait_3_missing(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_1(time_sleep, time_time): + """Test that wait_for_str_ordered() works for list""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" u.wait_for_str_ordered(["foo", "bar", "baz"], timeout=3) @@ -57,6 +61,7 @@ def test_wait_ordered_1(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_2_missing(time_sleep, time_time): + """Test that wait_for_str_ordered() asserts when string is missing""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" with pytest.raises(AssertionError) as ex_info: @@ -66,6 +71,7 @@ def test_wait_ordered_2_missing(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_3_out_of_order(time_sleep, time_time): + """Test that wait_for_str_ordered() asserts when strings are out of order""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" with pytest.raises(AssertionError) as ex_info: @@ -75,6 +81,7 @@ def test_wait_ordered_3_out_of_order(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_4_multiple(time_sleep, time_time): + """Test that wait_for_str_ordered() works for multiple identical strings""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\nfoo123\nfoo123\nbar123\n" u.wait_for_str_ordered(["foo", "foo", "foo"], timeout=3) @@ -82,6 +89,7 @@ def test_wait_ordered_4_multiple(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_5_overflow(time_sleep, time_time): + """Test that wait_for_str_ordered() asserts when too many identical strings""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\nfoo123\nfoo123\nbar123\n" with pytest.raises(AssertionError) as ex_info: @@ -91,6 +99,7 @@ def test_wait_ordered_5_overflow(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_6_out_of_order(time_sleep, time_time): + """Test that wait_for_str_ordered() asserts when strings are out of order""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\nfoo123\nfoo123\nbar123\n" with pytest.raises(AssertionError) as ex_info: @@ -100,6 +109,7 @@ def test_wait_ordered_6_out_of_order(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_ordered_7_none(time_sleep, time_time): + """Test that wait_for_str_ordered() asserts when no strings are found""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\nfoo123\nfoo123\nbar123\n" with pytest.raises(AssertionError) as ex_info: @@ -109,6 +119,7 @@ def test_wait_ordered_7_none(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_8_get_current_size(time_sleep, time_time): + """Test that wait_for_str() returns current log size""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" current_log_size = u.wait_for_str(["bar"], timeout=3) @@ -117,6 +128,7 @@ def test_wait_8_get_current_size(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_9_start_position(time_sleep, time_time): + """Test that wait_for_str() starts from given position""" u = mocked_uart() u.log = "foo123\nbar123\nbaz123\n" bar_pos = u.log.find("bar") @@ -128,6 +140,7 @@ def test_wait_9_start_position(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_10_extract_one_value(time_sleep, time_time): + """Test that extract_value() works for one value""" u = mocked_uart() u.log = "foo: 123.45\n bar: 23.45 \n baz: 0.1234\n" assert float(u.extract_value(r"bar: (\d.+)")[0]) == 23.45 @@ -135,6 +148,7 @@ def test_wait_10_extract_one_value(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_11_extract_three_values(time_sleep, time_time): + """Test that extract_value() works for multiple values""" u = mocked_uart() u.log = "foo: 123.45 bar: 23.45 baz: 0.1234" extrated_values = u.extract_value(r"foo: (\d.+) bar: (\d.+) baz: (\d.+)") @@ -143,6 +157,7 @@ def test_wait_11_extract_three_values(time_sleep, time_time): @patch("time.time", side_effect=counter()) @patch("time.sleep") def test_wait_12_extract_missing_values(time_sleep, time_time): + """Test that extract_value() returns None when values are missing""" u = mocked_uart() u.log = "foo: 123.45 baz: 23.45 bar: 0.1234" extrated_values = u.extract_value(r"foo: (\d.+) foo: (\d.+) foo: (\d.+)")