Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
210
tools/EVerest-main/tests/README.md
Normal file
210
tools/EVerest-main/tests/README.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# EVerest tests
|
||||
|
||||
This folder contains the basic test functions for EVerest's e2e testing. You can either extend the '*\*_tests.py*' files in the "EVerest/**tests/core_tests**" folder or write your own!
|
||||
|
||||
## Prerequisites
|
||||
|
||||
In order to run any of the e2e tests, you need to have EVerest compiled
|
||||
and installed on your system. Please also make sure to install the python
|
||||
requirements.
|
||||
|
||||
```bash
|
||||
cd EVerest/
|
||||
cmake -S . -B build -DBUILD_TESTING=ON
|
||||
cmake --build build --target install --parallel -j$(nproc)
|
||||
. build/venv/bin/activate
|
||||
cmake --build build --target everestpy_pip_install_dist # install everestpy
|
||||
cmake --build build --target everest-testing_pip_install_dist # install everest-testing
|
||||
cmake --build build --target iso15118_pip_install_dist # install iso15118 for ev side simulation
|
||||
python3 -m pip install "aiofile>=3.7.4"
|
||||
python3 -m pip install "netifaces>=0.11.0"
|
||||
```
|
||||
|
||||
## Execute locally
|
||||
|
||||
All test suites are run via the unified `run-tests.sh` script:
|
||||
|
||||
```bash
|
||||
cd ~/checkout/everest-workspace/EVerest/tests
|
||||
|
||||
./run-tests.sh all # all tests (core, framework, async, OCPP)
|
||||
./run-tests.sh core # core tests only
|
||||
./run-tests.sh framework # framework tests only
|
||||
./run-tests.sh asyncapi # async API tests only
|
||||
./run-tests.sh integration # core + framework + async
|
||||
./run-tests.sh ocpp # all OCPP tests (1.6, 2.0.1, 2.1)
|
||||
./run-tests.sh --serial all # run serially (no parallelism)
|
||||
./run-tests.sh -j4 all # limit to 4 parallel workers
|
||||
./run-tests.sh --help # show all options
|
||||
```
|
||||
|
||||
The script automatically sets up network isolation for parallel ISO 15118 tests
|
||||
(requires sudo or CAP_NET_ADMIN) and falls back to sequential execution otherwise.
|
||||
|
||||
After execution `result.xml` and `report.html` are written to the `tests/` directory.
|
||||
|
||||
### Running individual tests directly
|
||||
|
||||
For a single test file or test case, invoke `pytest` directly from the `tests/` directory:
|
||||
|
||||
```bash
|
||||
cd ~/checkout/everest-workspace/EVerest/tests
|
||||
|
||||
# Run a single test file
|
||||
python3 -m pytest core_tests/smoke_tests.py
|
||||
|
||||
# Run a single test by name
|
||||
python3 -m pytest core_tests/smoke_tests.py::test_iso15118_ac_session
|
||||
```
|
||||
|
||||
Network isolation is not set up automatically in this mode — ISO 15118 tests will
|
||||
run sequentially via their `xdist_group` marker.
|
||||
|
||||
## Add own test sets
|
||||
|
||||
To create own test sets, you need to write a new python file in the "EVerest/**tests/core_tests/**" folder. A basic file template would look like this:
|
||||
|
||||
```python
|
||||
import logging
|
||||
import pytest
|
||||
|
||||
from everest.testing.core_utils.fixtures import *
|
||||
from validations.base_functions import wait_for_and_validate_event
|
||||
from everest.testing.core_utils.test_control_module import TestControlModule
|
||||
from everest.testing.core_utils.everest_core import EverestCore
|
||||
from validations.user_functions import *
|
||||
|
||||
@ pytest.mark.asyncio
|
||||
async def test_001_my_first_test(everest_core: EverestCore,
|
||||
test_control_module: TestControlModule):
|
||||
logging.info(">>>>>>>>> test_001_my_first_test <<<<<<<<<")
|
||||
everest_core.start()
|
||||
|
||||
assert await wait_for_and_validate_event(test_control_module,
|
||||
exp_event='my_event',
|
||||
exp_data={"my_data":"test"},
|
||||
validation_function=my_validation_function,
|
||||
timeout=30)
|
||||
```
|
||||
|
||||
\*Note: All test functions' names NEED to start with "test" (see pytest documentation: https://docs.pytest.org/)
|
||||
|
||||
In the above example you then would also have to write a (user-)validation function by the name of "my_validation_function()" in the "EVerest/**tests/core_tests/validations/user_functions.py**" file.
|
||||
|
||||
For this, you can utilize helper functions from the "EVerest/**tests/core_tests/validations/base_functions.py**" file (e.g. "get_key_if_exists()" to traverse and retrieve event data from an event-object).
|
||||
|
||||
**Attention**: When you change something in the test- or validation files, please do not forget to run "*make install*" on EVerest before starting the tests, as otherwise the changes are not reflected in the test run!
|
||||
|
||||
### Controlling more functionality with PyTestControlModule
|
||||
|
||||
If you would like to receive other everest-internal data, send commands to other EVerest modules or would like to change the received events for everest-testing, you can modify the **PyTestControlModule** in the "EVerest/**modules/PyTestControlModule**" folder.
|
||||
|
||||
**Attention:** Please be aware, though, that the use of this module is preliminary and changes in the *everest-framework* may render this module **obsolete** in the future!
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**1. Problem:** Multiple concatenated tests that use the *PyTestControlModule* (in standalone configuration) result in an exception and subsequent crash of everest-testing.
|
||||
|
||||
**Cause:** There is currently no way to unload a module in *EVerest*. But because pytest runs out of the same context for all tests in a testset, a once loaded *PyTestControlModule* stays active for the rest of the pytest/everest-testing run. When a new test tries to load a second instance of the *PyTestControlModule* it collides with the already running instance and causes everest-testing to crash.
|
||||
|
||||
**Solution:** Unfortunately, this requires a change in the everest-framework. This change is currently under development, but not yet merged into main.
|
||||
For the moment, there is a *workaround available:* Use a new test-set (another python file containing a new set of tests) for every test that requires control via the *PyTestControlModule*. As soon as a fix for the underlying issue is merged, this will be updated!
|
||||
|
||||
**2. Problem:** On an unmodified run of "basic_charging_tests.py" the test *test_001_charge_defined_ammount* fails and reports an amount of 0.0kWh charged.
|
||||
|
||||
**Cause:** Currently there is a bug in the EVSE manager implementation in EVerest, causing a race-condition between resetting the "amount charged" parameter and the event reporting for a "*transaction_finished*" event. Sometimes it reports correctly, other times it reports a value of 0.0kWh charged.
|
||||
|
||||
**Solution:** This problem is known and a fix is under way. For the moment, just re-run the test. Usually, this should then produce a passing result.
|
||||
|
||||
|
||||
# Code coverage
|
||||
|
||||
To activate code coverage, you need to configure the project with
|
||||
`BUILD_TESTING` enabled. Furthermore, `gcovr` needs to be installed.
|
||||
|
||||
## Generating coverage reports
|
||||
|
||||
Before generating a coverage report you will typically need to run some
|
||||
executables or tests, which contain or link to code, that generates coverage
|
||||
statistics.
|
||||
|
||||
After that, just run:
|
||||
```bash
|
||||
cmake --build build --target everest-core_create_coverage
|
||||
# or ninja -C build everest-core_create_coverage
|
||||
```
|
||||
|
||||
The generated `index.html` will be available at
|
||||
`build/everest-core_create_coverage/index.html`.
|
||||
|
||||
**Note**: the code coverage for a specific compilation unit (cpp file) will
|
||||
accumulate if you run multiple executables that use this compilation unit. The
|
||||
code coverage is recorded in `gcda` files. If you want to get separate coverage
|
||||
reports for different executables, these `gcda` files need to be deleted for
|
||||
each new *run*.
|
||||
|
||||
|
||||
## Adding code/targets to code coverage
|
||||
|
||||
By default, all *cpp* modules are added automatically to a list of targets that
|
||||
will be compiled with coverage flags. If additional libraries or tests need to
|
||||
be added to code coverage, you should use the following functions in your
|
||||
*cmake* code:
|
||||
```cmake
|
||||
ev_register_library_target(LIBRARY_TARGET_NAME)
|
||||
ev_register_test_target(TEST_TARGET_NAME)
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
For the `ev_register_*_target` functions, call these function close to their
|
||||
scope of detail - meaning near `add_library` for libraries like:
|
||||
|
||||
```cmake
|
||||
add_library(evse_security_conversions STATIC)
|
||||
add_library(everest::evse_security_conversions ALIAS evse_security_conversions)
|
||||
ev_register_library_target(evse_security_conversions)
|
||||
```
|
||||
|
||||
and near `add_test` for tests like:
|
||||
|
||||
```cmake
|
||||
add_test(${TLS_GTEST_NAME} ${TLS_GTEST_NAME})
|
||||
ev_register_test_target(${TLS_GTEST_NAME})
|
||||
```
|
||||
|
||||
and not scattered around.
|
||||
|
||||
---
|
||||
|
||||
By default, all directories ending with `tests` will be excluded from the code
|
||||
coverage report (because we're not interested in the code coverage of the unit
|
||||
test code itself). So when adding unit tests for code coverage, place them into
|
||||
a `tests` folder.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
`no_working_dir_found`: while developing code (e.g. an `example.cpp`), it might
|
||||
happen, that the created object file `example.cpp.o` will get out of sync with
|
||||
its corresponding `example.cpp.gcno` (`gcov` note file) and/or
|
||||
`example.cpp.gcda` (`gcov` data file). When creating a report, `gcovr` will
|
||||
complain, because it can't find the corresponding `example.cpp.o` file for a
|
||||
stale `example.cpp.gcno` file. It might also not be able to find the
|
||||
`example.cpp.gcno` file for a stale `example.cpp.gcda` file or an older `gcda`
|
||||
file might got out of sync due to a newer `gcno` file and so forth. Do not
|
||||
simply ignore these warnings/errors, as the report might not be accurate
|
||||
anymore.
|
||||
|
||||
The current sledgehammer approach is to manually delete the files in question or
|
||||
just do (**be careful** with `rm` commands and wildcards!):
|
||||
```bash
|
||||
find ./build -name "*.gcno" -delete
|
||||
find ./build -name "*.gcda" -delete
|
||||
ninja -C build clean
|
||||
ninja -C build
|
||||
# run code
|
||||
# create coverage
|
||||
```
|
||||
|
||||
We're currently trying to write some tooling around this to make this more
|
||||
usable.
|
||||
Reference in New Issue
Block a user