Skip to content

Commit fd9e06a

Browse files
committed
Merge branch 'prepare-release-3.0.0' into 'master'
Prepare release 3.0.0 See merge request ins/nettowel/nettowel-nuts!37
2 parents 54c91bf + 137c94c commit fd9e06a

File tree

8 files changed

+188
-180
lines changed

8 files changed

+188
-180
lines changed

README.md

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Introduction
44

5-
The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project.
5+
The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland.
66
It draws on the concept of unit tests, known from the domain of programming, and applies it to the domain of networking.
77

88
One major difference between unit tests in programming and
@@ -14,18 +14,34 @@ pre-defined test cases. Such a single test case might be "can host A reach neigh
1414
This is what nuts tries to achieve:
1515
Apply test cases based on your pre-defined network topology to your actual network and have the tests confirm the correct state.
1616

17+
## Installation Instructions
18+
19+
### Using pip
20+
21+
Run `pip install nuts`
22+
23+
### Using poetry
24+
25+
Nuts uses [poetry](https://python-poetry.org/) as a dependency manager.
26+
27+
1. [Install poetry](https://python-poetry.org/docs/#installation).
28+
2. Clone this repository.
29+
3. Run `$ poetry install`
30+
31+
## How It Works: Test Bundles and Test Definitions
32+
1733
The project relies on the [pytest framework](https://docs.pytest.org/) to setup and execute the tests.
1834
Nuts itself is written as a custom pytest plugin. In the background, [nornir](https://nornir.readthedocs.io/)
1935
executes specific network tasks for the actual tests.
2036

21-
Additionally, nuts treats the test definition and the so-called test bundle as separate entities. The *test definition* is modeled as a custom `pytest.Class`, and a predefined set of test definitions can be found in the module `base_tests`. New test definitions can be added easily by the user of the plugin.
37+
Nuts treats the test definition and the so-called test bundle as separate entities. The *test definition* is modeled as a custom `pytest.Class`, and a predefined set of test definitions can be found in the nuts module `base_tests`. New test definitions can be added easily by the user of the plugin.
2238

2339
The *test bundle* is a file that is parsed by pytest. The file provides data on the desired network state and describes which test definitions should be collected and executed by pytest.
2440
The structure of the test bundle should enable people without in-depth python knowledge to add new test bundles or update existing ones to reflect changes in the network.
2541

2642
While the readme here is only a short overview, find the [documentation of nuts on readthedocs](https://nuts.readthedocs.io/en/latest/).
2743

28-
## Test bundle structure
44+
### Test Bundle Structure
2945

3046
Currently only yaml files are supported as test bundles,
3147
but other sources such as other file formats or database entries can be considered in later nuts versions.
@@ -42,7 +58,7 @@ Each test bundle contains the following structure:
4258
```
4359
`test_module`: The full path of the python module that contains the test class to be used.
4460
This value is optional if the test class is registered in `index.py` of the pytest-nuts plugin.
45-
Note that it can be relevant in which directory `pytest` is started if local test modules are used.
61+
Note that it can be relevant in which directory `pytest` is started if local test modules are used. Using `test_modules` allows you to write your own test classes. **Note: We currently do not support self-written test modules, since upcoming refactorings might introduce breaking changes.**
4662

4763
`test_class`: The name of the python class which contains the tests that should be executed.
4864
Note that currently every test in this class will be executed.
@@ -58,7 +74,7 @@ This allows the additional `max_drop` parameter in `test_execution`, since it is
5874

5975
`test_data`: Data that is used to parametrize the tests in the test class which have the `pytest.mark.nuts` annotation. It is additionally part of the `nuts_parameters` property.
6076

61-
### Examples
77+
### Example: CDP Neighbors
6278
Example of a test bundle for `TestNetmikoCdpNeighbors` which tests that `R1` is a CDP Neighbor of both `R2` and `R3`.
6379
This example creates three different tests, one for each entry in the `test_data` list.
6480

@@ -85,14 +101,7 @@ This example creates three different tests, one for each entry in the `test_data
85101
...
86102
```
87103

88-
## Manual installation instructions
89-
Nuts uses [poetry](https://python-poetry.org/) as a dependency manager.
90-
91-
1. [Install poetry](https://python-poetry.org/docs/#installation).
92-
2. Clone this repository.
93-
3. Run `$ poetry install`
94-
95-
## Technical Overview
104+
### How the Test Bundle Is Converted to a Pytest Test
96105

97106
When nuts is executed, pytest converts the test bundles (the yaml files) into tests. During test collection, the custom pytest marker `nuts` uses the data that has been defined in the test bundle mentioned above.
98107
This annotation is a wrapper around the `pytest.mark.parametrize` annotation and allows the plugin to use the data entries from the test bundle. For each entry in the `test_data` section of the test bundle, the custom marker generates a single test case. To achieve this, the plugin transforms the entries into n-tuples, since `pytest.mark.parametrize` expects a list of n-tuples as input.
@@ -102,18 +111,16 @@ For each entry in `test_data` these fields are extracted and transformed to a tu
102111
If any of these fields are not present in an entry of `test_data`, the corresponding test case will be skipped.
103112
A second argument determines optional fields that can also be used in a test case as well - non-present values are passed into the function as `None`.
104113

105-
#### Example of a test class with custom marker
114+
The following test-run of CDP neighbors for example checks the local port:
106115

107116
```python
108-
@pytest.mark.usefixtures("check_nuts_result") # see below
117+
@pytest.mark.usefixtures("check_nuts_result")
109118
class TestNetmikoCdpNeighbors:
110119
@pytest.mark.nuts("host,remote_host,local_port")
111120
def test_local_port(self, single_result, remote_host, local_port):
112121
assert single_result.result[remote_host]["local_port"] == local_port
113122
```
114123

115-
This test-run of CDP neighbors checks the local port.
116-
117124
Before each test evaluation, the fixture `@pytest.mark.usefixtures("check_nuts_result")` checks the result of the network information that has been gathered by nornir in the background: It asserts that that no exception was thrown while doing so.
118125

119126
The required fields are `host`, `remote_host` and `local_port` - they must be present in the custom marker,
@@ -125,16 +132,18 @@ but also be provided as argument to the test method itself.
125132
Each test module implements a context class to provide module-specific functionality to its tests. This context class is a `NutsContext` or a subclass of it.
126133
This guarantees a consistent interface across all tests for test setup and execution.
127134
Currently, the predefined test classes use [nornir](https://nornir.readthedocs.io/en/latest/) in order to communicate
128-
with the network devices, therefore the test classes derive all from a more specific `NornirNutsContext`,
129-
which provides a nornir instance and nornir-specific helpers.
135+
with the network devices. Those test classes derive all from a more specific `NornirNutsContext`,
136+
which provides a nornir instance and nornir-specific helpers. In the example above, it is a class called `CdpNeighborsContext` that derives from `NornirNutsContext`.
137+
138+
If you want to learn more how nuts works but do not have a running network in the background, there's a nuts showcase - an offline test class that displays the basic functionality of nuts. See the [tutorial](https://nuts.readthedocs.io/en/latest/tutorial/firststeps.html) for further information.
130139

131-
## Development
140+
## Develop Your Own Test Classes
132141

133142
Nuts is essentially designed as a pytest-plugin and it is possible to add your own, self-written test classes.
134-
A dev documentation on how to write your own test classes is planned for the future.
135-
Until then, please read the regular [documentation of nuts](https://nuts.readthedocs.io/en/latest/) on how to use it.
143+
A dev documentation on how to write your own test classes is planned for a future release.
144+
Still, it is possible to write your own test classes nevertheless, even if we cannot guarantee that upcoming planned refactorings do not introduce breaking changes.
136145

137146
# Thanks
138147

139148
* [Matthias Gabriel](https://github.com/MatthiasGabriel), who laid the foundations of nuts.
140-
* [Florian Bruhin](https://github.com/The-Compiler) for invaluable feedback.
149+
* [Florian Bruhin (The Compiler)](https://github.com/The-Compiler) for invaluable feedback and advice.

docs/source/conf.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,19 @@
1212
#
1313
import os
1414
import sys
15+
import datetime
1516

1617
sys.path.insert(0, os.path.abspath("../.."))
1718
sys.setrecursionlimit(1500)
1819

1920
# -- Project information -----------------------------------------------------
2021

2122
project = "NUTS"
22-
copyright = "2020, Matthias Gabriel, Méline Sieber, Urs Baumann"
23-
author = "Matthias Gabriel, Méline Sieber, Urs Baumann"
23+
copyright = f"{datetime.date.today().year}, Méline Sieber, Urs Baumann"
24+
author = "Méline Sieber"
2425

2526
# The full version, including alpha/beta/rc tags
26-
release = "0.1.0"
27+
release = "1.0.0"
2728

2829

2930
# -- General configuration ---------------------------------------------------

docs/source/dev/index.rst

Lines changed: 0 additions & 6 deletions
This file was deleted.

docs/source/index.rst

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,40 @@ Documentation of NUTS
66
Introduction
77
------------
88

9-
The NetTowel Network Unit Testing System or "NUTS" for short is the
10-
testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland.
11-
NUTS draws on the concept of unit tests, known from the domain of
12-
software development, and applies it to the domain of networking.
13-
14-
One major difference between unit tests in software development and
15-
network tests is the definition of a test.
16-
In software development, unit tests normally focus on testing edge cases,
17-
since the amount of non-edge cases is not definable.
18-
In the network testing domain, tests are less about edge cases, but more about testing network functionalities with pre-defined test cases. Such a single test case might be "can host A
19-
reach neighbors X, Y, Z?" or "has host A all BGP neighbors configured correctly?" on many different devices.
20-
21-
This is what NUTS tries to achieve:
22-
Use pre-defined test cases together with your network topology, apply this to your actual network and have the tests confirm that the network has the expected functionalities.
23-
24-
How NUTS works
9+
The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland.
10+
It draws on the concept of unit tests, known from the domain of programming, and applies it to the domain of networking.
11+
12+
One major difference between unit tests in programming and
13+
network tests is the definition of what a test actually is.
14+
In programming, unit tests normally focus on testing edge cases,
15+
since the amount of non-edge cases is not definable.
16+
In the network testing domain, tests are less about edge cases, but more about testing existing network states with
17+
pre-defined test cases. Such a single test case might be "can host A reach neighbors X, Y, Z?" on many different devices.
18+
This is what nuts tries to achieve:
19+
Apply test cases based on your pre-defined network topology to your actual network and have the tests confirm the correct state.
20+
21+
How nuts works
2522
--------------
2623

27-
In order to run NUTS, two components are required:
24+
In order to run nuts, two components are required:
2825

2926
#. **Inventory of the network**. Currently, these are YAML-files in the form of a `nornir inventory <https://nornir.readthedocs.io/en/latest/tutorial/inventory.html>`__. They contain all details of your network, such as hosts, login-information and other configuration.
3027

3128
#. **Test bundles** in the form of YAML-files that specify the actual tests. A test bundle is a series of tests that are logically related to each other. Each test bundle is structured in a similar way, but has specific fields tailored to the test bundle. Some field values in a test bundle are directly related to your inventory.
3229

33-
Head over to the :doc:`Usage section <tutorial/firststeps>` to see how those two components are structured and how you get NUTS up and running.
30+
Head over to the :doc:`Usage section <tutorial/firststeps>` to see how those two components are structured and how you get nuts up and running.
3431

3532
The project relies on the `pytest framework <https://docs.pytest.org/>`__ to setup and execute the
36-
tests. NUTS itself is written as a custom pytest plugin. In the background, `nornir <https://nornir.readthedocs.io/>`__ executes specific network tasks for the actual tests.
33+
tests. Nuts itself is written as a custom pytest plugin. In the background, `nornir <https://nornir.readthedocs.io/>`__ executes specific network tasks for the actual tests.
3734

38-
Pytest reads in the test bundle (2.) and transforms it into test runs. In the background, nornir uses the network information provided in the inventory (1.), queries the network based on the specific test bundle and passes the results of those queries to pytest. Pytest then evaluates if the expectations defined in the test bundle match those results.
35+
Pytest reads in the test bundle (step 2 above) and transforms it into test runs. In the background, nornir uses the network information provided in the inventory (step 1 above), queries the network based on the specific test bundle and passes the results of those queries to pytest. Pytest then evaluates if the expectations defined in the test bundle match those results.
3936

40-
Enhance NUTS
37+
Enhance nuts
4138
------------
42-
Since NUTS is written as a pytest plugin and in python, you can customize it yourself and write your own test classes. Please see the :doc:`development section <dev/index>` to see how NUTS is structured and how to write your own test classes.
39+
Nuts is written in python and designed as a pytest plugin. It provides some base tests described in :doc:`the section about all test bundles <testbundles/alltestbundles>`, but since it's a plugin, you can write your own, self-written test classes for your custom tests.
40+
A dev documentation on how to write your own test classes is planned for a future release.
4341

42+
We do not support self-written tests at the moment, since planned refactorings might introduce breaking changes. Still, you can already write your own test classes - see the ``nuts/base_tests`` folder in the code repository to learn how test classes are written.
4443

4544
Contents
4645
========
@@ -49,10 +48,9 @@ Contents
4948
:maxdepth: 2
5049

5150
Home <self>
52-
Installation <installation/index>
51+
Installation <installation/install>
5352
Tutorial <tutorial/firststeps>
5453
Test Bundles <testbundles/alltestbundles>
55-
Development <dev/index>
5654

5755

5856
Indices and tables

docs/source/installation/index.rst renamed to docs/source/installation/install.rst

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,25 @@ Installation of NUTS
44
Installation Instructions
55
-------------------------
66

7-
NUTS is currently not published on the Python Package Index (`PyPI <https://pypi.org/>`_). It has to be cloned and installed manually.
7+
Nuts requires Python 3.7 or higher.
88

9-
.. todo::
10-
11-
Use public repository to access code and retest the installation instructions.
12-
13-
.. code:: shell
9+
Installation via pip
10+
....................
1411

15-
git clone <public repository>
12+
NUTS is published on the Python Package Index (`PyPI <https://pypi.org/>`_), therefore you can install nuts using ``pip``:
1613

17-
cd nettowel-nuts
14+
.. code:: shell
1815
19-
# create virtual environment
20-
python -m venv .venv
16+
pip install nuts
2117
22-
# activate virtual environment
23-
source .venv/bin/activate
18+
Installation via poetry
19+
.......................
2420

25-
# install NUTS
26-
pip install <your_nuts_directory>
21+
Nuts uses `poetry <https://python-poetry.org/>`__ as a dependency manager.
2722

28-
# install NUTS directly from git without clone first
29-
pip install git+https://github.com/INSRapperswil/Nuts.git
23+
1. `Install poetry <https://python-poetry.org/docs/#installation>`__.
24+
2. Clone the `nuts repository <https://github.com/INSRapperswil/Nuts.git>`__
25+
3. Run ``$ poetry install``
3026

3127
Parsing with ntc-templates
3228
--------------------------
@@ -54,7 +50,7 @@ Deinstallation
5450

5551
.. code:: shell
5652
57-
pip uninstall nettowel-nuts
53+
pip uninstall nuts
5854
5955
6056
If you installed everything in a virtual environment, you can delete the folder that contains the virtual environment.

docs/source/testbundles/alltestbundles.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ A test bundle contains one ore more tests that are logically related to each oth
55

66
This section contains all test bundles which have been implemented in NUTS, you can incorporate them in your own bundles. They can be executed with the command ``$ pytest <test>.yaml`` from your project root.
77

8-
Note that you need an inventory for the tests to work. Please see :doc:`First Steps with NUTS <../tutorial/firststeps>` for more information.
8+
Note that you need an inventory of network devices for the tests to work. Please see :doc:`First Steps with NUTS <../tutorial/firststeps>` for more information.
99

1010
In some test bundles you can directly pass arguments to the nornir task, i.e. the network query that is executed in the background. For those test bundles we indicate the specific task which is used to query the devices, so that you can look up all available arguments.
1111

0 commit comments

Comments
 (0)