Help is welcome, and you can contribute in various ways:
- Write new test cases to extend coverage of the RFC.
- Point out issues in existing test cases, e.g., if the RFC was not interpreted correctly by the test authors.
- Implement new keywords in the DSL, or fix existing ones.
- Provide additional test data that is specific to your use case.
Contributions are made through pull requests, or by filing an issue in the repository.
tests- test scenarios written with keywords implemented in RF (Robot Framework)resources- source code of the keywords themselves, written in RF or Pythondata- pre-generated test data (e.g., keys, certificates) used in some test casesconfig- configuration options (e.g., IP addresses, port numbers, etc.) for target environments to testunit_tests- tests for the Python primitives of the library itselfdoc- generated documentation of the test suite and its keywords
- Install the dependencies:
pip install -r requirements-dev.txtto use tools for linting, type checking, etc. - If using IntelliJ or PyCharm, set the source directory:
File/Project Structure/Modules, click on theresourcesfolder, selectSourceand apply. - You can also do this in the code, e.g., if not using an IDE
import sys; sys.path.append("./resources")
For more details about usage of RF with an IDE: https://docs.robotframework.org/docs/getting_started/ide.
In many cases it is better to use the same data across runs, instead of generating something on-the-fly. This supports replicability, because the test will always send the same data, therefore it is easier for the authors of the system under test to answer the question "what exactly happened when the error occurred?". Consider the example of sending a CSR - if you generate it on-the-fly, its signature will be different, even if everything else in the CSR is identical.
Follow these principles when building your tests:
- if possible, use the same data all the time (e.g., by loading a payload from a file)
- include the tool (function, script, list of steps, etc.) that was used to generate the file
- allow exceptions to the rule if necessary, e.g. a nonce or timestamp might have to be unique in a particular scenario
A good practice is to generate new data on-demand once, e.g., by running a script that generates all the required data, and then using the same data in subsequent runs. Make sure to document the process of generating the data!
Prefer to store data in textual form, rather than binary. This makes it easier to visually inspect the data, copy some chunks for experimentation, logging, or for sharing with colleagues.
For example, payloads in PKI are often DER-encoded, but you can also use PEM. The difference in storage size can be neglected, while transforming one into the other is easy and can be automated (e.g., write keywords and functions that convert automatically to whatever makes sense, and accept either format at the input).
Each test scenario aims at a section of the RFC where a given requirement is discussed. Refer to this section in the documentation of the test and include a relevant quote. The quote must be concise, so the intention of the test can be understood at a glance without having to read the RFC itself.
When updating or adding new keywords, regenerate the documentation with make doc and ensure that the updated doc/
is included in the repository. This is done for the benefit of those who explore the test suite and its capabilities -
they should be able to do so without having to read the source code or prepare the environment where make doc can be
executed.
Use top-level imports when importing modules. Otherwise, the documentation generated by Robot Framework will also include all the functions of the module, adding noise.
Example: write import cryptoutils and call cryptoutils.sign_data in your code, rather than
from cryptoutils import sign_data.
Due to a discrepancy between the docstring style expected by ruff and the one used by RobotFramework, we sometimes
ignore ruff. Such places are marked with # noqa: D417 for RF docs, because the docstrings are tuned to look good
in the RobotFramework documentation. Look for this comment in the code to see examples of how to write the docstrings.
Consider what tags can be used to categorize your tests. Their main benefit is that the test suite can be run in a way that includes or excludes specific tests, such that you can focus on evaluating specific functionality.
Throughout the test suite, you will encounter places where numeric parameters are passed as strings. This is because
RF will pass a parameter as a string unless you convert it to an integer, i.e., 2 is passed as "2" (str), while
${2} is passed as 2 (number). For convenience, we allow both notations and encourage the use of the string notation,
such that the test cases are more readable.
On a source code level, see typingutils.Strint, which stands for "stringified integer".
By default, RF will expose all Python functions as keywords for the test suite. You can suppress that with the
not_keyword decorator: robot.api.deco.not_keyword. When writing new Python functions, consider whether they need
to be exposed or not. Here is how one can use the decorator:
@not_keyword
def this_is_not_a_keyword():
pass
-
Where
univ.<ClassName>appears in the code comments, it is assumed to refer to thepyasn1.type.univ, e.g.,univ.ObjectIdentifier -
When you encounter
rfc<num>.<ClassName>, it is assumed to be frompyasn1_alt_modules, e.g.,from pyasn1_alt_modules import rfc9480. Example:rfc9480.PKIMessage.
This section explains how OpenSSL can be used to generate test data, such as key-pairs or CSRs.
- Get list of supported algorithms
openssl list -signature-algorithms, let's say you will useRSA. - Generate a private key
openssl genpkey -algorithm RSA -out private-key-rsa.pem. - Generate a CSR
openssl req -new -key private-key-rsa.pem -out csr-rsa.pem -nodes -subj /CN=testSubject(note that on Windows you might have to write the latter part as//CN=testSubject). - Generate a PKIMessage
ir:openssl cmp -cmd ir -server https://example.com/.well-known/cmp -recipient //CN=test -ref 11111 -csr csr-rsa.pem -secret pass:presharedPass -popo 1 -certout result-cert.pem -newkey private-key-rsa.pem -reqout req-ir.pkimessage
- The code passes the CI pipeline checks.
- References to specific RFC sections are provided when relevant.
- If reporting errors in the test suite, include a report generated by RF.
- The documentation of keywords is up-to-date.
- The generated documentation is in
doc/. - Python keyword docstrings follow the RF conventions.
- Unnecessary Python functions are masked.
- The test data is stored in textual form.
- The test data does not contain sensitive information (e.g., department identifiers or personal data).
- Private keys and other test data are not taken from production systems.