This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| automation:test-the-network [2025/07/06 07:16] – jotasandoku | automation:test-the-network [2025/07/18 22:04] (current) – jotasandoku | ||
|---|---|---|---|
| Line 2: | Line 2: | ||
| * **Unit testing (atomic level)** - individual functions/ | * **Unit testing (atomic level)** - individual functions/ | ||
| * Component testing - groups of related units working together | * Component testing - groups of related units working together | ||
| - | * **Integration testing** - multiple components | + | * **Integration testing** - multiple components |
| * System testing - entire application | * System testing - entire application | ||
| + | ---- | ||
| + | |||
| + | |||
| + | ====PYATS=== | ||
| + | * {{ : | ||
| + | * {{ : | ||
| + | * {{ : | ||
| + | |||
| + | Topics | ||
| + | * ' | ||
| + | * TestScripts: | ||
| + | * Jobs: executes TestScripts as tasks. Also allows to execute multiple TestScripts in parallel | ||
| + | |||
| + | * pyATS library (Genie): Data PARSING. Tooling used to extract the network data. | ||
| + | * Genie Harness: Used to build **test cases using YAML datafiles** | ||
| + | |||
| + | * Easypy - Runtime | ||
| + | * Others: Blitz, Clean, ' | ||
| + | * AEtest (Easy Testing): scaffolding/ | ||
| + | |||
| + | |||
| + | === TESTSCRIPT === | ||
| + | Is the python file that holds all your tests. | ||
| + | |||
| + | * Common setup: Initial configuration and device initialization including loops - decorator : '' | ||
| + | * Testcases: ' | ||
| + | * Cleanup: Resets the testing environment after the test - decorator: '' | ||
| + | |||
| + | ** see slides 46,47 for examples (classes..)) ** | ||
| + | \\ | ||
| + | Test Parameters: TestScript > Testcase > TestSection | ||
| + | |||
| + | * Callable | ||
| + | * Test Parameters - decorator : '' | ||
| + | * Test Execution: | ||
| + | * Standalone: all logging is sent to stdout. See slide 64-65 | ||
| + | * Easypy: Standardized runtime env within pyATS. Helpful for regression testing | ||
| + | ---- | ||
| ---- | ---- | ||
| ==== OPTIONS ==== | ==== OPTIONS ==== | ||
| === Classic1: Unittest / **pytest** libraries === | === Classic1: Unittest / **pytest** libraries === | ||
| - | TODO | ||
| - | |||
| - | === Modern1: PyATS === | ||
| == Assertions == | == Assertions == | ||
| * **Definition: | * **Definition: | ||
| Line 39: | Line 74: | ||
| * Provide setup logic for tests; Can include teardown logic after the test (using `yield`); Can be reused across multiple tests; Can depend on other fixtures; Can be parameterised | * Provide setup logic for tests; Can include teardown logic after the test (using `yield`); Can be reused across multiple tests; Can depend on other fixtures; Can be parameterised | ||
| - | **Example1: | + | **Example1: |
| import pytest | import pytest | ||
| - | |||
| @pytest.fixture | @pytest.fixture | ||
| def greeting(): | def greeting(): | ||
| return "hello world" | return "hello world" | ||
| - | |||
| def test_uppercase(greeting): | def test_uppercase(greeting): | ||
| assert greeting.upper() == "HELLO WORLD" | assert greeting.upper() == "HELLO WORLD" | ||
| - | |||
| def test_length(greeting): | def test_length(greeting): | ||
| assert len(greeting) == 11 | assert len(greeting) == 11 | ||
| - | **Fixture with Setup and Teardown**: The yield keyword pauses the fixture until the test finishes, then resumes for any cleanup. | + | **Fixture with Setup and Teardown**: The yield keyword pauses the fixture until the test finishes, then resumes for any cleanup. This fixture uses **yield** to provide a temporary **file path to the test**, allowing the test to use the file as needed. Once the test finishes, the code after the yield runs as the teardown phase — perfect for cleanup or logging. The tmp_path argument itself is a built-in pytest fixture that provides a temporary directory, which ensures isolation and avoids side effects between tests. |
| import pytest | import pytest | ||
| @pytest.fixture | @pytest.fixture | ||
| Line 62: | Line 94: | ||
| # Cleanup code here (e.g. delete or log) | # Cleanup code here (e.g. delete or log) | ||
| - | ** Dependent Fixtures **: Fixtures can call other fixtures automatically. | + | ** Dependent Fixtures **: Fixtures can call other fixtures automatically. Here, the **user_token** fixture depends on the user_data fixture, which pytest resolves automatically. This shows how fixtures can be layered: one fixture can receive another as a parameter, enabling you to build more complex test setups from smaller, testable pieces. The test then uses user_token without needing to worry about where or how the token was created — the fixtures manage it all behind the scenes. |
| @pytest.fixture | @pytest.fixture | ||
| def user_data(): | def user_data(): | ||
| return {" | return {" | ||
| - | |||
| @pytest.fixture | @pytest.fixture | ||
| def user_token(user_data): | def user_token(user_data): | ||
| return f" | return f" | ||
| - | |||
| def test_token(user_token): | def test_token(user_token): | ||
| assert user_token.startswith(" | assert user_token.startswith(" | ||
| | | ||
| - | ** Parametrised Fixtures ** : The test runs once for each value of the user parameter. | + | ** Parametrised Fixtures ** : The test runs once for each value of the user parameter. |
| @pytest.fixture(params=[" | @pytest.fixture(params=[" | ||
| def user(request): | def user(request): | ||
| return request.param | return request.param | ||
| - | |||
| def test_starts_lowercase(user): | def test_starts_lowercase(user): | ||
| assert user[0].islower() | assert user[0].islower() | ||
| | | ||
| - | | + | ** restapi test ** |
| + | In this example, we are testing the REST API of a network device. The api_base_url fixture provides the root URL of the API, which could represent a router or switch’s management interface. The auth_headers fixture supplies the necessary HTTP headers for authenticating the request, such as a bearer token and the content type. These two fixtures are injected into the test function, which uses them to send a GET request to the /interfaces endpoint. The test asserts that the response status is 200 (OK), and that the response JSON contains an " | ||
| + | import pytest | ||
| + | import requests | ||
| - | ---- | + | @pytest.fixture |
| + | def api_base_url(): | ||
| + | return " | ||
| + | @pytest.fixture | ||
| + | def auth_headers(): | ||
| + | return { | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | def test_get_interfaces(api_base_url, | ||
| + | url = f" | ||
| + | response = requests.get(url, | ||
| + | assert response.status_code == 200 | ||
| + | assert " | ||
| - | ===== Further Reading ===== | ||
| - | [[https:// | ||
| - | [[https:// | ||
| - | [[https:// | + | ===== Further Reading ===== |
| - | + | ||
| - | [[https:// | + | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | ---- | + | |
| - | + | ||
| - | == Parametrization | + | |
| - | * **Definition: | + | |
| - | * **Usage:** Implemented with < | + | |
| - | * **Example: | + | |
| - | <code python> | + | |
| - | @pytest.mark.parametrize(" | + | |
| - | def test_ping(ip): | + | |
| - | assert ping(ip) | + | |
| - | </ | + | |
| - | * **Purpose: | + | |
| - | + | ||
| - | ---- | + | |
| - | + | ||
| - | == Other Relevant Concepts | + | |
| - | * **Testcase/ | + | |
| - | * A testcase is a Python class, often subclassing < | + | |
| - | * A testscript is a file containing one or more testcases. | + | |
| - | * **Sections: | + | |
| - | * Special methods within a testcase, such as < | + | |
| - | * **Testbed: | + | |
| - | * A YAML or Python file describing devices and connections used in tests. | + | |
| - | * **Loggers: | + | |
| - | * Used for reporting test steps and results (< | + | |
| - | * **aetest:** | + | |
| - | * Core pyATS test harness module for organizing and running tests. | + | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | ---- | + | |
| - | == Examples == | + | * [[https:// |
| - | * NUTS (network unit tests): [[https:// | + | * [[https:// |
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||