Skip to content

Latest commit

 

History

History
235 lines (174 loc) · 8.58 KB

contribution.md

File metadata and controls

235 lines (174 loc) · 8.58 KB
anta_title
How to contribute to ANTA

Contribution model is based on a fork-model. Don't push to aristanetworks/anta directly. Always do a branch in your forked repository and create a PR.

To help development, open your PR as soon as possible even in draft mode. It helps other to know on what you are working on and avoid duplicate PRs.

Create a development environment

Run the following commands to create an ANTA development environment:

# Clone repository
$ git clone https://github.com/aristanetworks/anta.git
$ cd anta

# Install ANTA in editable mode and its development tools
$ pip install -e .[dev]
# To also install the CLI
$ pip install -e .[dev,cli]

# Verify installation
$ pip list -e
Package Version Editable project location
------- ------- -------------------------
anta    1.1.0   /mnt/lab/projects/anta

Then, tox is configured with few environments to run CI locally:

$ tox list -d
default environments:
clean  -> Erase previous coverage reports
lint   -> Check the code style
type   -> Check typing
py39   -> Run pytest with py39
py310  -> Run pytest with py310
py311  -> Run pytest with py311
py312  -> Run pytest with py312
report -> Generate coverage report

Code linting

tox -e lint
[...]
lint: commands[0]> ruff check .
All checks passed!
lint: commands[1]> ruff format . --check
158 files already formatted
lint: commands[2]> pylint anta

--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)

lint: commands[3]> pylint tests

--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)

  lint: OK (22.69=setup[2.19]+cmd[0.02,0.02,9.71,10.75] seconds)
  congratulations :) (22.72 seconds)

Code Typing

tox -e type

[...]
type: commands[0]> mypy --config-file=pyproject.toml anta
Success: no issues found in 68 source files
type: commands[1]> mypy --config-file=pyproject.toml tests
Success: no issues found in 82 source files
  type: OK (31.15=setup[14.62]+cmd[6.05,10.48] seconds)
  congratulations :) (31.18 seconds)

NOTE: Typing is configured quite strictly, do not hesitate to reach out if you have any questions, struggles, nightmares.

Unit tests

To keep high quality code, we require to provide a Pytest for every tests implemented in ANTA.

All submodule should have its own pytest section under tests/units/anta_tests/<submodule-name>.py.

How to write a unit test for an AntaTest subclass

The Python modules in the tests/units/anta_tests folder define test parameters for AntaTest subclasses unit tests. A generic test function is written for all unit tests in tests.units.anta_tests module.

The pytest_generate_tests function definition in conftest.py is called during test collection.

The pytest_generate_tests function will parametrize the generic test function based on the DATA data structure defined in tests.units.anta_tests modules.

See https://docs.pytest.org/en/7.3.x/how-to/parametrize.html#basic-pytest-generate-tests-example

The DATA structure is a list of dictionaries used to parametrize the test. The list elements have the following keys:

  • name (str): Test name as displayed by Pytest.
  • test (AntaTest): An AntaTest subclass imported in the test module - e.g. VerifyUptime.
  • eos_data (list[dict]): List of data mocking EOS returned data to be passed to the test.
  • inputs (dict): Dictionary to instantiate the test inputs as defined in the class from test.
  • expected (dict): Expected test result structure, a dictionary containing a key result containing one of the allowed status (Literal['success', 'failure', 'unset', 'skipped', 'error']) and optionally a key messages which is a list(str) and each message is expected to be a substring of one of the actual messages in the TestResult object.

In order for your unit tests to be correctly collected, you need to import the generic test function even if not used in the Python module.

Test example for anta.tests.system.VerifyUptime AntaTest.

# Import the generic test function
from tests.units.anta_tests import test

# Import your AntaTest
from anta.tests.system import VerifyUptime

# Define test parameters
DATA: list[dict[str, Any]] = [
   {
        # Arbitrary test name
        "name": "success",
        # Must be an AntaTest definition
        "test": VerifyUptime,
        # Data returned by EOS on which the AntaTest is tested
        "eos_data": [{"upTime": 1186689.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
        # Dictionary to instantiate VerifyUptime.Input
        "inputs": {"minimum": 666},
        # Expected test result
        "expected": {"result": "success"},
    },
    {
        "name": "failure",
        "test": VerifyUptime,
        "eos_data": [{"upTime": 665.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
        "inputs": {"minimum": 666},
        # If the test returns messages, it needs to be expected otherwise test will fail.
        # NB: expected messages only needs to be included in messages returned by the test. Exact match is not required.
        "expected": {"result": "failure", "messages": ["Device uptime is 665.15 seconds"]},
    },
]

Git Pre-commit hook

pip install pre-commit
pre-commit install

When running a commit or a pre-commit check:

❯ pre-commit
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check for added large files..............................................Passed
check for merge conflicts................................................Passed
Check and insert license on Python files.................................Passed
Check and insert license on Markdown files...............................Passed
Run Ruff linter..........................................................Passed
Run Ruff formatter.......................................................Passed
Check code style with pylint.............................................Passed
Checks for common misspellings in text files.............................Passed
Check typing with mypy...................................................Passed
Check Markdown files style...............................................Passed

Configure MYPYPATH

In some cases, mypy can complain about not having MYPYPATH configured in your shell. It is especially the case when you update both an anta test and its unit test. So you can configure this environment variable with:

# Option 1: use local folder
export MYPYPATH=.

# Option 2: use absolute path
export MYPYPATH=/path/to/your/local/anta/repository

Documentation

mkdocs is used to generate the documentation. A PR should always update the documentation to avoid documentation debt.

Install documentation requirements

Run pip to install the documentation requirements from the root of the repo:

pip install -e .[doc]

Testing documentation

You can then check locally the documentation using the following command from the root of the repo:

mkdocs serve

By default, mkdocs listens to http://127.0.0.1:8000/, if you need to expose the documentation to another IP or port (for instance all IPs on port 8080), use the following command:

mkdocs serve --dev-addr=0.0.0.0:8080

Build class diagram

To build class diagram to use in API documentation, you can use pyreverse part of pylint with graphviz installed for jpeg generation.

pyreverse anta --colorized -a1 -s1 -o jpeg -m true -k --output-directory docs/imgs/uml/ -c <FQDN anta class>

Image will be generated under docs/imgs/uml/ and can be inserted in your documentation.

Checking links

Writing documentation is crucial but managing links can be cumbersome. To be sure there is no dead links, you can use muffet with the following command:

muffet -c 2 --color=always http://127.0.0.1:8000 -e fonts.gstatic.com -b 8192

Continuous Integration

GitHub actions is used to test git pushes and pull requests. The workflows are defined in this directory. The results can be viewed here.