-
Notifications
You must be signed in to change notification settings - Fork 0
Testing
To use pytest with the proposed directory structure, you'll follow a few key practices to ensure pytest can discover and execute your tests, even with different levels of nesting and organization. Here's how you can set it up:
Make sure you have pytest installed in your virtual environment:
pip install pytestpytest automatically discovers test files and functions based on their names. For smooth integration with your directory structure:
-
Test files should be named with the prefix
test_or suffix_test. For example,test_openplc.pyoropenplc_test.py. -
Test functions should also follow the same naming convention, starting with
test_, e.g.,def test_modbus_communication():.
For pytest to recognize directories as Python packages, you might need to add an empty __init__.py file in directories containing Python test code.
For example:
tests/
├── __init__.py # Marks tests directory as a Python package
├── openplc/
│ ├── python/
│ │ ├── __init__.py # Marks python directory as a package
│ │ ├── test_openplc.py # Contains your pytest tests
This ensures pytest recognizes your structure, but depending on the Python version, it may not be strictly necessary anymore.
To execute all tests, navigate to your project’s root directory (where docker_compose.yml, Makefile, and README.md are located) and simply run:
pytestThis will:
- Automatically find all
test_*.pyor*_test.pyfiles. - Collect test functions from those files and execute them.
pytest will recursively look for tests in subdirectories like tests/openplc/python/ and tests/scada_lts/python/.
If you have common setup code (e.g., starting up a container or initializing a simulation), you can define it as a fixture in a conftest.py file, which pytest automatically discovers.
For example, in tests/conftest.py:
import pytest
@pytest.fixture(scope="module")
def modbus_connection():
# Set up your Modbus connection or mock here
connection = setup_modbus_connection()
yield connection
# Teardown the connection after the test is done
connection.close()Then in your tests (e.g., tests/openplc/python/test_openplc.py):
def test_modbus_read(modbus_connection):
result = modbus_connection.read_holding_registers(1, 10)
assert result == expected_valueFor tests that aren't Python-based (like PLC programs or SCADA configuration tests), you can still organize them under tests/openplc/non-python/ or tests/scada_lts/non-python/. While pytest won't execute these files directly, you can create Python test scripts that:
- Call external command-line tools to run these tests.
- Validate the expected results (e.g., checking that the PLC program loads successfully).
For example, in tests/openplc/non-python/test_plc_load.py:
import subprocess
def test_plc_program_load():
# Example of calling an external tool or script
result = subprocess.run(['openplc_runtime', '--load', 'path_to_plc_program.st'], capture_output=True, text=True)
assert "Load successful" in result.stdoutYou can run specific test directories or files with pytest. For example:
- Run only OpenPLC tests:
pytest tests/openplc
- Run a specific test file:
pytest tests/scada_lts/python/test_scada.py
├── docker_compose.yml
├── LICENSE
├── Makefile
├── openplc/
│ └── src/
│ └── files/
├── scada_lts/
│ └── hmi/
├── simulations/
│ └── irrigation_simulator.py
│ └── main.py
│ └── modbus_io.py
├── tests/
│ ├── conftest.py # Shared pytest fixtures
│ ├── openplc/
│ │ ├── python/
│ │ │ └── test_openplc.py
│ │ └── non-python/
│ │ └── test_plc_load.py
│ ├── scada_lts/
│ │ ├── python/
│ │ └── non-python/
│ ├── simulations/
│ │ └── python/
│ ├── integration/
│ │ └── python/
│ │ └── non-python/
├── README.md
This setup keeps everything clean and manageable while ensuring pytest can handle both Python and non-Python aspects of your project. Let me know if you need more details on a specific part!