baldertest


Namebaldertest JSON
Version 0.1.0b10 PyPI version JSON
download
home_pagehttps://docs.balder.dev
Summarybalder: reusable scenario based test framework
upload_time2024-11-14 11:38:11
maintainerNone
docs_urlNone
authorMax Stahlschmidt and others
requires_python>=3.9
licenseMIT
keywords test systemtest reusable scenario
VCS
bugtrack_url
requirements alabaster Babel certifi charset-normalizer docutils idna imagesize furo Jinja2 MarkupSafe packaging Pygments pyparsing pytz pytest pylint requests snowballstemmer Sphinx sphinxcontrib-applehelp sphinxcontrib-devhelp sphinxcontrib-htmlhelp sphinxcontrib-jsmath sphinxcontrib-mermaid sphinxcontrib-qthelp sphinxcontrib-serializinghtml urllib3
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
<div align="center">
  <img style="margin: 20px;max-width: 68%" src="https://docs.balder.dev/en/latest/_static/balder_w_boarder.png" alt="Balder logo">
</div>

Balder is a very powerful, universal and flexible python test system that allows you to reuse a once written testcode as 
efficiently as possible for different but similar platforms/devices/applications. Balder's goal is
being a platform for combining the single steps of defining, developing and documenting the entire test 
process while using test scenarios which can be reused across different projects.

You can share your own testcode by creating a new BalderHub project, or you use an 
[existing BalderHub project](https://hub.balder.dev), by simply installing and using it. This makes the test development 
for your project much faster, since it is often times enough to only provide the user-specific code.

Be part of the progress and share your tests with others, your company or the whole world.

# Installation

You can install the latest release with pip:

```
python -m pip install baldertest
```

# Run Balder

After you've installed it, you can run Balder inside a Balder environment with the following command:

```
balder
```

You can also provide a specific path to the balder environment directory by using this console argument:

```
balder --working-dir /path/to/working/dir
```

# How does it work?

Balder allows you to reuse previously written test code by dividing it into the components that **are needed** for a 
test (`Scenario`) and the components that **we have** (`Setup`).

`Scenario` classes define a test. Only describe the most important aspects **you need** for the execution of the 
corresponding test (method of the scenario class) inside `Scenario` classes. Often it is enough to define abstract 
methods in the scenario-level features.

In contrast, `Setup` classes describe exactly what **you have**. This is where you define all the devices and their 
features. Balder will then automatically search for mappings and run your test with them.

## Define the `Scenario` class

Inside `Scenario` or `Setup` classes, inner `Device` classes describe your environment. For example, if you want to test 
the process of sending a message between two devices, you can create a `Scenario` like shown below:

```python
import balder
from .features import SendMessageFeature, RecvMessageFeature


class ScenarioMessaging(balder.Scenario):
    
    class Sender(balder.Device):
        send = SendMessageFeature()
    
    @balder.connect(Sender, over_connection=balder.Connection())
    class Receiver(balder.Device):
        recv = RecvMessageFeature()
        
    

```

You have now defined, that the `Sender` device must be able to send messages (has `SendMessageFeature()`), while 
the `Receiver` device must be able to receive messages (has `RecvMessageFeature()`). Both devices are connected with 
each other. For this we use the general connection `balder.Connection()`, which allows every type of connection.

You can implement your test, by adding a new method that starts with `test_*()`:

```python
import balder
from .features import SendMessageFeature, RecvMessageFeature


class ScenarioMessaging(balder.Scenario):
    
    class Sender(balder.Device):
        send = SendMessageFeature()
    
    @balder.connect(Sender, over_connection=balder.Connection())
    class Receiver(balder.Device):
        recv = RecvMessageFeature()
        
    def test_send_msg(self):
        MESSAGE_TXT = "Hello World"
        self.Sender.send.send_msg(MESSAGE_TXT)
        received_msg = self.Receiver.recv.get_last_received_msg()
        assert received_msg == MESSAGE_TXT

```

## Define the `Setup` class

The next step is defining a `Setup` class, which describes what we have. For a `Scenario` to match a `Setup`, all of 
your scenario-devices must be able to map to a sub selection of some setup-devices. 

For example, if you want to verify if your DUT is able to receive messages from your computer (both are connected over 
USB), just create a `Setup` class with the both devices `Computer` and `Dut` and add an implementation (subclasses) of 
our previously defined feature classes `SendMessageFeature` and `RecvMessageFeature` to them:

```python
import balder
from balder import connections as cnns
from .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature


class SetupOverUsb(balder.Setup):
    
    class Computer(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendUsbMessageFeature()
    
    @balder.connect(Computer, over_connection=cnns.UsbConnection())
    class Dut(balder.Device):
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()

```

With the features `SendUsbMessageFeature` and `RecvUsbMessageFeature`, both devices hold an implementation of our 
previous scenario-level features `SendMessageFeature` and `RecvMessageFeature`. They are the child classes of our
scenario-level features and hold the full implementation for sending/receiving data over USB.

As soon as you run Balder, Balder will automatically detect that our scenario `ScenarioMessaging` can be mapped to the 
`SetupOverUsb`. This will cause Balder to run the test `test_send_msg()` with the implemented setup-level version of 
the features.

The big advantage of Balder is the reusability. If you want to test if the communication also works in the other 
direction, just add the features inverted:

```python
import balder
from balder import connections as cnns
from .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature


class SetupOverUsb(balder.Setup):
    
    class Computer(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendUsbMessageFeature()
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()
    
    @balder.connect(Computer, over_connection=cnns.UsbConnection())
    class Dut(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendUsbMessageFeature()
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()

```

Balder will now run the test once with the `Computer` being the sender and once with the `Dut` being the Sender, even 
though you didn't implement anything new.

|             | `ScenarioMessaging.Sender` | `ScenarioMessaging.Sender` |
|-------------|----------------------------|----------------------------|
| VARIATION 1 | `SetupOverUsb.Computer`    | `SetupOverUsb.Dut`         |
| VARIATION 2 | `SetupOverUsb.Dut`         | `SetupOverUsb.Computer`    |

Do you have another device, that should be tested too? Just add it to your setup:

```python
import balder
from balder import connections as cnns
from .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature


class SetupOverUsb(balder.Setup):
    
    class Computer(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendUsbMessageFeature()
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()
    
    @balder.connect(Computer, over_connection=cnns.UsbConnection())
    class Dut(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendUsbMessageFeature()
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()
        
    @balder.connect(Computer, over_connection=cnns.UsbConnection())
    class AnotherDut(balder.Device):
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvUsbMessageFeature()

```

Now balder will run our scenario once each with the following mappings:

|             | `ScenarioMessaging.Sender` | `ScenarioMessaging.Sender` |
|-------------|----------------------------|----------------------------|
| VARIATION 1 | `SetupOverUsb.Computer`    | `SetupOverUsb.Dut`         |
| VARIATION 2 | `SetupOverUsb.Dut`         | `SetupOverUsb.Computer`    |
| VARIATION 3 | `SetupOverUsb.Computer`    | `SetupOverUsb.AnotherDut`  |

If you want to test a `Dut` device that does not use USB for communication, you can also add other feature 
implementations of ``SendMessageFeature`` and ``RecvMessageFeature`` in your setup devices. For this we just add a new 
setup:

```python
import balder
from balder import connections as cnns
from .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature, SendBluetoothMessageFeature, RecvBluetoothMessageFeature


class SetupOverUsb(balder.Setup):
    
    ...

class SetupOverBluetooth(balder.Setup):
    class Computer(balder.Device):
        # non-abstract subclass of `SendMessageFeature`
        send = SendBluetoothMessageFeature()
    
    @balder.connect(Computer, over_connection=cnns.BluetoothConnection)
    class Dut(balder.Device):
        # non-abstract subclass of `RecvMessageFeature`
        recv = RecvBluetoothMessageFeature()

```

If you now execute Balder, it will run the scenario with all possible device constellations of the `SetupOverUsb` and 
the `SetupOverBluetooth`. 

|             | `ScenarioMessaging.Sender`      | `ScenarioMessaging.Sender` |
|-------------|---------------------------------|----------------------------|
| VARIATION 1 | `SetupOverUsb.Computer`         | `SetupOverUsb.Dut`         |
| VARIATION 2 | `SetupOverUsb.Dut`              | `SetupOverUsb.Computer`    |
| VARIATION 3 | `SetupOverUsb.Computer`         | `SetupOverUsb.AnotherDut`  |
| VARIATION 4 | `SetupOverBluetooth.Computer`   | `SetupOverBluetooth.Dut`   |

NOTE: *You could also add all of these devices in a shared setup and use one common feature for both protocols, but for this you would need to use VDevices. You can read more about this in [the documentation section about VDevices](https://docs.balder.dev/en/latest/basics/vdevices.html)*


# Example: Use an installable BalderHub package

With Balder you can create custom test environments or install open source available test packages, so called 
[BalderHub packages](https://hub.balder.dev). If you want to test a SNMP client device for example, you can use the 
[package balderhub-snmpagent](https://github.com/balder-dev/balderhub-snmpagent). Just install it with:

```
$ pip install balderhub-snmpagent
```

You only need to provide two things: The configuration of your DUT as subclass of `SnmpSystemConfig` and your 
environment (the `Setup` class):

```python
# file `features.py`
from balderhub.snmpagent.lib import features

class MySnmpSystemConfig(features.SnmpSystemConfig):

    host = "192.168.178.28"
    sys_descr = "my fancy sysDescr"
    sys_object_id = "1.3.6.1.4.1.1234.2.3.9.1"
    read_community = "public"
    write_community = "public"

```

```python
# file `setup_example.py`
import balder
from balderhub.snmpagent.lib.connections import SnmpConnection
from balderhub.snmpagent.lib.features import HasSnmpSystemGroupFeature
from balderhub.snmpagent.lib.setup_features import SendSnmpGetRequestPysnmpFeature, SendSnmpSetRequestPysnmpFeature
from . import features as setup_features


class SetupPrinter(balder.Setup):

    class Printer(balder.Device):
        _snmp_sys = HasSnmpSystemGroupFeature()
        config = setup_features.SnmpSystemConfig()

    @balder.connect(Printer, over_connection=SnmpConnection())
    class HostPc(balder.Device):
        get_request_snmp = SendSnmpGetRequestPysnmpFeature()
        set_request_snmp = SendSnmpSetRequestPysnmpFeature()

```

Call Balder in your project:

```
$ balder
```

And all existing and matching tests in [balderhub-snmpagent](https://github.com/balder-dev/balderhub-snmpagent) will 
then be executed for you:

```
+----------------------------------------------------------------------------------------------------------------------+
| BALDER Testsystem                                                                                                    |
|  python version 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] | balder version 0.1.0b6                           |
+----------------------------------------------------------------------------------------------------------------------+
Collect 1 Setups and 3 Scenarios
  resolve them to 3 mapping candidates

================================================== START TESTSESSION ===================================================
SETUP SetupPrinter
  SCENARIO ScenarioMibSysDescr
    VARIATION ScenarioMibSysDescr.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysDescr.SnmpManager:SetupPrinter.HostPc
      TEST ScenarioMibSysDescr.test_get_sys_descr [.]
      TEST ScenarioMibSysDescr.test_get_sys_descr_ascii_check [.]
      TEST ScenarioMibSysDescr.test_set_sys_descr [.]
  SCENARIO ScenarioMibSysObjectId
    VARIATION ScenarioMibSysObjectId.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysObjectId.SnmpManager:SetupPrinter.HostPc
      TEST ScenarioMibSysObjectId.test_get_sys_object_id [.]
      TEST ScenarioMibSysObjectId.test_set_sys_object_id [.]
  SCENARIO ScenarioMibSysUpTime
    VARIATION ScenarioMibSysUpTime.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysUpTime.SnmpManager:SetupPrinter.HostPc
      TEST ScenarioMibSysUpTime.test_get_sys_up_time [.]
      TEST ScenarioMibSysUpTime.test_get_sys_up_time_changed_check [.]
      TEST ScenarioMibSysUpTime.test_set_sys_up_time [.]
================================================== FINISH TESTSESSION ==================================================
TOTAL NOT_RUN: 0 | TOTAL FAILURE: 0 | TOTAL ERROR: 0 | TOTAL SUCCESS: 8 | TOTAL SKIP: 0 | TOTAL COVERED_BY: 0
```


# Contribution guidelines

Any help is appreciated. If you want to contribute to balder, take a look into the 
[contribution guidelines](https://github.com/balder-dev/balder/blob/main/CONTRIBUTING.md).

Balder is still in its early steps. Unfortunately, this also means that we don't have a broad variety of 
[BalderHub projects](https://hub.balder.dev) at the moment. 

Are you an expert in your field? Do you enjoy the concept of balder? How about you create your own
BalderHub project? Take a look into our [Balder GitHub Group](https://github.com/balder-dev) and feel free to share 
your ideas. You can contribute to an existing project or create your own. If you are not sure, a project for your idea 
already exists or if you want to discuss your ideas with others, feel free to
[create an issue in the BalderHub main entry project](https://github.com/balder-dev/hub.balder.dev/issues) or
[start a new discussion](https://github.com/balder-dev/hub.balder.dev/discussions).

# License

Balder is free and Open-Source

Copyright (c) 2022 Max Stahlschmidt and others

Distributed under the terms of the MIT license

            

Raw data

            {
    "_id": null,
    "home_page": "https://docs.balder.dev",
    "name": "baldertest",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "test, systemtest, reusable, scenario",
    "author": "Max Stahlschmidt and others",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/de/d3/3afc36bb03f36f5db8c911683114c83418a34d5585f8c44bb8a8952faafb/baldertest-0.1.0b10.tar.gz",
    "platform": "unix",
    "description": "\n<div align=\"center\">\n  <img style=\"margin: 20px;max-width: 68%\" src=\"https://docs.balder.dev/en/latest/_static/balder_w_boarder.png\" alt=\"Balder logo\">\n</div>\n\nBalder is a very powerful, universal and flexible python test system that allows you to reuse a once written testcode as \nefficiently as possible for different but similar platforms/devices/applications. Balder's goal is\nbeing a platform for combining the single steps of defining, developing and documenting the entire test \nprocess while using test scenarios which can be reused across different projects.\n\nYou can share your own testcode by creating a new BalderHub project, or you use an \n[existing BalderHub project](https://hub.balder.dev), by simply installing and using it. This makes the test development \nfor your project much faster, since it is often times enough to only provide the user-specific code.\n\nBe part of the progress and share your tests with others, your company or the whole world.\n\n# Installation\n\nYou can install the latest release with pip:\n\n```\npython -m pip install baldertest\n```\n\n# Run Balder\n\nAfter you've installed it, you can run Balder inside a Balder environment with the following command:\n\n```\nbalder\n```\n\nYou can also provide a specific path to the balder environment directory by using this console argument:\n\n```\nbalder --working-dir /path/to/working/dir\n```\n\n# How does it work?\n\nBalder allows you to reuse previously written test code by dividing it into the components that **are needed** for a \ntest (`Scenario`) and the components that **we have** (`Setup`).\n\n`Scenario` classes define a test. Only describe the most important aspects **you need** for the execution of the \ncorresponding test (method of the scenario class) inside `Scenario` classes. Often it is enough to define abstract \nmethods in the scenario-level features.\n\nIn contrast, `Setup` classes describe exactly what **you have**. This is where you define all the devices and their \nfeatures. Balder will then automatically search for mappings and run your test with them.\n\n## Define the `Scenario` class\n\nInside `Scenario` or `Setup` classes, inner `Device` classes describe your environment. For example, if you want to test \nthe process of sending a message between two devices, you can create a `Scenario` like shown below:\n\n```python\nimport balder\nfrom .features import SendMessageFeature, RecvMessageFeature\n\n\nclass ScenarioMessaging(balder.Scenario):\n    \n    class Sender(balder.Device):\n        send = SendMessageFeature()\n    \n    @balder.connect(Sender, over_connection=balder.Connection())\n    class Receiver(balder.Device):\n        recv = RecvMessageFeature()\n        \n    \n\n```\n\nYou have now defined, that the `Sender` device must be able to send messages (has `SendMessageFeature()`), while \nthe `Receiver` device must be able to receive messages (has `RecvMessageFeature()`). Both devices are connected with \neach other. For this we use the general connection `balder.Connection()`, which allows every type of connection.\n\nYou can implement your test, by adding a new method that starts with `test_*()`:\n\n```python\nimport balder\nfrom .features import SendMessageFeature, RecvMessageFeature\n\n\nclass ScenarioMessaging(balder.Scenario):\n    \n    class Sender(balder.Device):\n        send = SendMessageFeature()\n    \n    @balder.connect(Sender, over_connection=balder.Connection())\n    class Receiver(balder.Device):\n        recv = RecvMessageFeature()\n        \n    def test_send_msg(self):\n        MESSAGE_TXT = \"Hello World\"\n        self.Sender.send.send_msg(MESSAGE_TXT)\n        received_msg = self.Receiver.recv.get_last_received_msg()\n        assert received_msg == MESSAGE_TXT\n\n```\n\n## Define the `Setup` class\n\nThe next step is defining a `Setup` class, which describes what we have. For a `Scenario` to match a `Setup`, all of \nyour scenario-devices must be able to map to a sub selection of some setup-devices. \n\nFor example, if you want to verify if your DUT is able to receive messages from your computer (both are connected over \nUSB), just create a `Setup` class with the both devices `Computer` and `Dut` and add an implementation (subclasses) of \nour previously defined feature classes `SendMessageFeature` and `RecvMessageFeature` to them:\n\n```python\nimport balder\nfrom balder import connections as cnns\nfrom .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature\n\n\nclass SetupOverUsb(balder.Setup):\n    \n    class Computer(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendUsbMessageFeature()\n    \n    @balder.connect(Computer, over_connection=cnns.UsbConnection())\n    class Dut(balder.Device):\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n\n```\n\nWith the features `SendUsbMessageFeature` and `RecvUsbMessageFeature`, both devices hold an implementation of our \nprevious scenario-level features `SendMessageFeature` and `RecvMessageFeature`. They are the child classes of our\nscenario-level features and hold the full implementation for sending/receiving data over USB.\n\nAs soon as you run Balder, Balder will automatically detect that our scenario `ScenarioMessaging` can be mapped to the \n`SetupOverUsb`. This will cause Balder to run the test `test_send_msg()` with the implemented setup-level version of \nthe features.\n\nThe big advantage of Balder is the reusability. If you want to test if the communication also works in the other \ndirection, just add the features inverted:\n\n```python\nimport balder\nfrom balder import connections as cnns\nfrom .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature\n\n\nclass SetupOverUsb(balder.Setup):\n    \n    class Computer(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendUsbMessageFeature()\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n    \n    @balder.connect(Computer, over_connection=cnns.UsbConnection())\n    class Dut(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendUsbMessageFeature()\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n\n```\n\nBalder will now run the test once with the `Computer` being the sender and once with the `Dut` being the Sender, even \nthough you didn't implement anything new.\n\n|             | `ScenarioMessaging.Sender` | `ScenarioMessaging.Sender` |\n|-------------|----------------------------|----------------------------|\n| VARIATION 1 | `SetupOverUsb.Computer`    | `SetupOverUsb.Dut`         |\n| VARIATION 2 | `SetupOverUsb.Dut`         | `SetupOverUsb.Computer`    |\n\nDo you have another device, that should be tested too? Just add it to your setup:\n\n```python\nimport balder\nfrom balder import connections as cnns\nfrom .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature\n\n\nclass SetupOverUsb(balder.Setup):\n    \n    class Computer(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendUsbMessageFeature()\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n    \n    @balder.connect(Computer, over_connection=cnns.UsbConnection())\n    class Dut(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendUsbMessageFeature()\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n        \n    @balder.connect(Computer, over_connection=cnns.UsbConnection())\n    class AnotherDut(balder.Device):\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvUsbMessageFeature()\n\n```\n\nNow balder will run our scenario once each with the following mappings:\n\n|             | `ScenarioMessaging.Sender` | `ScenarioMessaging.Sender` |\n|-------------|----------------------------|----------------------------|\n| VARIATION 1 | `SetupOverUsb.Computer`    | `SetupOverUsb.Dut`         |\n| VARIATION 2 | `SetupOverUsb.Dut`         | `SetupOverUsb.Computer`    |\n| VARIATION 3 | `SetupOverUsb.Computer`    | `SetupOverUsb.AnotherDut`  |\n\nIf you want to test a `Dut` device that does not use USB for communication, you can also add other feature \nimplementations of ``SendMessageFeature`` and ``RecvMessageFeature`` in your setup devices. For this we just add a new \nsetup:\n\n```python\nimport balder\nfrom balder import connections as cnns\nfrom .setup_features import SendUsbMessageFeature, RecvUsbMessageFeature, SendBluetoothMessageFeature, RecvBluetoothMessageFeature\n\n\nclass SetupOverUsb(balder.Setup):\n    \n    ...\n\nclass SetupOverBluetooth(balder.Setup):\n    class Computer(balder.Device):\n        # non-abstract subclass of `SendMessageFeature`\n        send = SendBluetoothMessageFeature()\n    \n    @balder.connect(Computer, over_connection=cnns.BluetoothConnection)\n    class Dut(balder.Device):\n        # non-abstract subclass of `RecvMessageFeature`\n        recv = RecvBluetoothMessageFeature()\n\n```\n\nIf you now execute Balder, it will run the scenario with all possible device constellations of the `SetupOverUsb` and \nthe `SetupOverBluetooth`. \n\n|             | `ScenarioMessaging.Sender`      | `ScenarioMessaging.Sender` |\n|-------------|---------------------------------|----------------------------|\n| VARIATION 1 | `SetupOverUsb.Computer`         | `SetupOverUsb.Dut`         |\n| VARIATION 2 | `SetupOverUsb.Dut`              | `SetupOverUsb.Computer`    |\n| VARIATION 3 | `SetupOverUsb.Computer`         | `SetupOverUsb.AnotherDut`  |\n| VARIATION 4 | `SetupOverBluetooth.Computer`   | `SetupOverBluetooth.Dut`   |\n\nNOTE: *You could also add all of these devices in a shared setup and use one common feature for both protocols, but for this you would need to use VDevices. You can read more about this in [the documentation section about VDevices](https://docs.balder.dev/en/latest/basics/vdevices.html)*\n\n\n# Example: Use an installable BalderHub package\n\nWith Balder you can create custom test environments or install open source available test packages, so called \n[BalderHub packages](https://hub.balder.dev). If you want to test a SNMP client device for example, you can use the \n[package balderhub-snmpagent](https://github.com/balder-dev/balderhub-snmpagent). Just install it with:\n\n```\n$ pip install balderhub-snmpagent\n```\n\nYou only need to provide two things: The configuration of your DUT as subclass of `SnmpSystemConfig` and your \nenvironment (the `Setup` class):\n\n```python\n# file `features.py`\nfrom balderhub.snmpagent.lib import features\n\nclass MySnmpSystemConfig(features.SnmpSystemConfig):\n\n    host = \"192.168.178.28\"\n    sys_descr = \"my fancy sysDescr\"\n    sys_object_id = \"1.3.6.1.4.1.1234.2.3.9.1\"\n    read_community = \"public\"\n    write_community = \"public\"\n\n```\n\n```python\n# file `setup_example.py`\nimport balder\nfrom balderhub.snmpagent.lib.connections import SnmpConnection\nfrom balderhub.snmpagent.lib.features import HasSnmpSystemGroupFeature\nfrom balderhub.snmpagent.lib.setup_features import SendSnmpGetRequestPysnmpFeature, SendSnmpSetRequestPysnmpFeature\nfrom . import features as setup_features\n\n\nclass SetupPrinter(balder.Setup):\n\n    class Printer(balder.Device):\n        _snmp_sys = HasSnmpSystemGroupFeature()\n        config = setup_features.SnmpSystemConfig()\n\n    @balder.connect(Printer, over_connection=SnmpConnection())\n    class HostPc(balder.Device):\n        get_request_snmp = SendSnmpGetRequestPysnmpFeature()\n        set_request_snmp = SendSnmpSetRequestPysnmpFeature()\n\n```\n\nCall Balder in your project:\n\n```\n$ balder\n```\n\nAnd all existing and matching tests in [balderhub-snmpagent](https://github.com/balder-dev/balderhub-snmpagent) will \nthen be executed for you:\n\n```\n+----------------------------------------------------------------------------------------------------------------------+\n| BALDER Testsystem                                                                                                    |\n|  python version 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] | balder version 0.1.0b6                           |\n+----------------------------------------------------------------------------------------------------------------------+\nCollect 1 Setups and 3 Scenarios\n  resolve them to 3 mapping candidates\n\n================================================== START TESTSESSION ===================================================\nSETUP SetupPrinter\n  SCENARIO ScenarioMibSysDescr\n    VARIATION ScenarioMibSysDescr.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysDescr.SnmpManager:SetupPrinter.HostPc\n      TEST ScenarioMibSysDescr.test_get_sys_descr [.]\n      TEST ScenarioMibSysDescr.test_get_sys_descr_ascii_check [.]\n      TEST ScenarioMibSysDescr.test_set_sys_descr [.]\n  SCENARIO ScenarioMibSysObjectId\n    VARIATION ScenarioMibSysObjectId.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysObjectId.SnmpManager:SetupPrinter.HostPc\n      TEST ScenarioMibSysObjectId.test_get_sys_object_id [.]\n      TEST ScenarioMibSysObjectId.test_set_sys_object_id [.]\n  SCENARIO ScenarioMibSysUpTime\n    VARIATION ScenarioMibSysUpTime.SnmpAgent:SetupPrinter.Printer | ScenarioMibSysUpTime.SnmpManager:SetupPrinter.HostPc\n      TEST ScenarioMibSysUpTime.test_get_sys_up_time [.]\n      TEST ScenarioMibSysUpTime.test_get_sys_up_time_changed_check [.]\n      TEST ScenarioMibSysUpTime.test_set_sys_up_time [.]\n================================================== FINISH TESTSESSION ==================================================\nTOTAL NOT_RUN: 0 | TOTAL FAILURE: 0 | TOTAL ERROR: 0 | TOTAL SUCCESS: 8 | TOTAL SKIP: 0 | TOTAL COVERED_BY: 0\n```\n\n\n# Contribution guidelines\n\nAny help is appreciated. If you want to contribute to balder, take a look into the \n[contribution guidelines](https://github.com/balder-dev/balder/blob/main/CONTRIBUTING.md).\n\nBalder is still in its early steps. Unfortunately, this also means that we don't have a broad variety of \n[BalderHub projects](https://hub.balder.dev) at the moment. \n\nAre you an expert in your field? Do you enjoy the concept of balder? How about you create your own\nBalderHub project? Take a look into our [Balder GitHub Group](https://github.com/balder-dev) and feel free to share \nyour ideas. You can contribute to an existing project or create your own. If you are not sure, a project for your idea \nalready exists or if you want to discuss your ideas with others, feel free to\n[create an issue in the BalderHub main entry project](https://github.com/balder-dev/hub.balder.dev/issues) or\n[start a new discussion](https://github.com/balder-dev/hub.balder.dev/discussions).\n\n# License\n\nBalder is free and Open-Source\n\nCopyright (c) 2022 Max Stahlschmidt and others\n\nDistributed under the terms of the MIT license\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "balder: reusable scenario based test framework",
    "version": "0.1.0b10",
    "project_urls": {
        "Homepage": "https://docs.balder.dev",
        "Source": "https://github.com/balder-dev/balder",
        "Tracker": "https://github.com/balder-dev/balder/issues"
    },
    "split_keywords": [
        "test",
        " systemtest",
        " reusable",
        " scenario"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cb29eebfb57df402a5b145851f3714e88f6066d99ad14d330cfcdd5048cc942c",
                "md5": "756c07a9fb456dfa7807c7f3716db91a",
                "sha256": "d453b1ad0ac0d8c75a314a410949fe1897245a69b2895701f2b5c12812985930"
            },
            "downloads": -1,
            "filename": "baldertest-0.1.0b10-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "756c07a9fb456dfa7807c7f3716db91a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 140363,
            "upload_time": "2024-11-14T11:38:09",
            "upload_time_iso_8601": "2024-11-14T11:38:09.852389Z",
            "url": "https://files.pythonhosted.org/packages/cb/29/eebfb57df402a5b145851f3714e88f6066d99ad14d330cfcdd5048cc942c/baldertest-0.1.0b10-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ded33afc36bb03f36f5db8c911683114c83418a34d5585f8c44bb8a8952faafb",
                "md5": "3806a2e563160e858fd24543bab58c87",
                "sha256": "aaca760293944d516745b694eb7720de4a4c885a467ebc8b87bec85be5982770"
            },
            "downloads": -1,
            "filename": "baldertest-0.1.0b10.tar.gz",
            "has_sig": false,
            "md5_digest": "3806a2e563160e858fd24543bab58c87",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 1497671,
            "upload_time": "2024-11-14T11:38:11",
            "upload_time_iso_8601": "2024-11-14T11:38:11.396538Z",
            "url": "https://files.pythonhosted.org/packages/de/d3/3afc36bb03f36f5db8c911683114c83418a34d5585f8c44bb8a8952faafb/baldertest-0.1.0b10.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-14 11:38:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "balder-dev",
    "github_project": "balder",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "alabaster",
            "specs": [
                [
                    "==",
                    "0.7.12"
                ]
            ]
        },
        {
            "name": "Babel",
            "specs": [
                [
                    "==",
                    "2.9.1"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2024.7.4"
                ]
            ]
        },
        {
            "name": "charset-normalizer",
            "specs": [
                [
                    "==",
                    "2.0.6"
                ]
            ]
        },
        {
            "name": "docutils",
            "specs": [
                [
                    "==",
                    "0.17.1"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "3.7"
                ]
            ]
        },
        {
            "name": "imagesize",
            "specs": [
                [
                    "==",
                    "1.2.0"
                ]
            ]
        },
        {
            "name": "furo",
            "specs": [
                [
                    "==",
                    "2022.1.2"
                ]
            ]
        },
        {
            "name": "Jinja2",
            "specs": [
                [
                    "==",
                    "3.1.4"
                ]
            ]
        },
        {
            "name": "MarkupSafe",
            "specs": [
                [
                    "==",
                    "2.0.1"
                ]
            ]
        },
        {
            "name": "packaging",
            "specs": [
                [
                    "==",
                    "21.0"
                ]
            ]
        },
        {
            "name": "Pygments",
            "specs": [
                [
                    "==",
                    "2.15.0"
                ]
            ]
        },
        {
            "name": "pyparsing",
            "specs": [
                [
                    "==",
                    "2.4.7"
                ]
            ]
        },
        {
            "name": "pytz",
            "specs": [
                [
                    "==",
                    "2021.3"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "==",
                    "6.2.5"
                ]
            ]
        },
        {
            "name": "pylint",
            "specs": [
                [
                    "==",
                    "3.2.5"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.32.2"
                ]
            ]
        },
        {
            "name": "snowballstemmer",
            "specs": [
                [
                    "==",
                    "2.1.0"
                ]
            ]
        },
        {
            "name": "Sphinx",
            "specs": [
                [
                    "==",
                    "4.2.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-applehelp",
            "specs": [
                [
                    "==",
                    "1.0.2"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-devhelp",
            "specs": [
                [
                    "==",
                    "1.0.2"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-htmlhelp",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-jsmath",
            "specs": [
                [
                    "==",
                    "1.0.1"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-mermaid",
            "specs": [
                [
                    "==",
                    "0.7.1"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-qthelp",
            "specs": [
                [
                    "==",
                    "1.0.3"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-serializinghtml",
            "specs": [
                [
                    "==",
                    "1.1.5"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "1.26.19"
                ]
            ]
        }
    ],
    "lcname": "baldertest"
}
        
Elapsed time: 0.34746s