Skip to content

Writing Your First Test: As Python Code

scorbettUM edited this page Mar 1, 2022 · 1 revision

Now that we now how to navigate Hedra's built in documentation, let's write our first test as Python code! To begin, create a file called my_test.py by running the command:

touch my_test.py

Let's then adding the following imports at the top of the file:

from hedra.testing import (
    ActionSet,
    use,
    action,
    Test
)

We'll be introducing parts of Hedra's Testing library piece by piece here, starting with test configuration via the Test class. Add the following code below the imports:

class Config(Test):
    embedded_stats=True
    engine_type='fast-http'
    batch_size=8000
    batch_time=10
    total_time="00:01:00"
  

We begin by creating a Config class that inherits the Test class, then specify several class parameters as below:

  • embedded_stats - Runs an embedded instance of Statserve, a GRPC-based streaming stats computation service, for results calculation.
  • engine_type - The type of engine we wish to use, analogous to the --engine CLI argument.
  • batch_size - The size of each concurrent "batch".
  • batch_time - The amount of time Hedra will wait for a batch to complete before moving on to the next batch.
  • total_time - The total amount of time the test should run.

Hedra knows to automatically import the class inheriting the Test class prior to running any test specified in the file, and will consume the configuration specified.

Note that you can only specify one such class per test file, and that Hedra will apply the specified configuration to all tests specified within the given file. This is to ensure streamlined execution of code-based tests.


Next, lets declare our test! Much like with the Test class, we'll create a class that inherits the ActionSet class:

class ExampleTest(ActionSet):
    pass

As with the Config class, Hedra will automatically import the class inheriting the ActionSet class. However, unlike the Config class, we can declare as many classes that inherit from the ActionSet class as we want. This allows us to write independent workflows and organize tests as independent modules.


Let's take the next step in writing our test by utilizing the use "hook" to make our ExampleTest class aware of the test configuration.

@use(Config)
class ExampleTest(ActionSet):
    pass

Hooks are functions provided by the Hedra's Testing library that wrap classes or functions, providing an accessible interface by which we can configure and specify test or individual action behavior. In the example above, we wrap our ExampleTest class with the use() hook, passing our Config class. This makes the configuration available to the ExampleTest class and provides pre-configured internal objects (such as an HTTP client session) to the selected engine.

The use() hook also allows us to (optionally) pass custom session objects for certain engines, however for this example we won't be needing this functionality.


Let's next write our first as-code action. Actions are specified as async methods of a given class that inherits from ActionSet wrapped in the action() hook.

@use(Config)
class ExampleTest(ActionSet):

    @action('httpbin_get')
    async def httpbin_get(self):
        return await self.execute({
                'method': 'GET',
                'endpoint': '/get',
                'host': 'https://httpbin.org'
            })

Here, we define an action called httpbin_get that makes a GET request to https://httpbin.org/get, return the result once completed. We declare the action as asynchronous method with no additional parameters, wrapping the method in the action() hook and passing the name of the action to the hook (this is a required argument for the action() hook). Within the method, we call the execute() method, which is inherited from the ActionSet class, passing a Python dictionary containing the data required by an action for the engine type selected.


Now That we completed writing our test, let's run it! In your terminal, run the following command:

hedra --code-filepath my_test.py

Hedra will first boot up the embedded instance of Statserve, then run the stages specified for the pipeline (setup, execute, and results in this case). Beginning with the setup stage, Hedra will parse the config specified by our Config class as well as the action(s) specified by our ExampleTest class. Upon parsing the config and actions, Hedra will then setup and configure the Persona and Engines specified.

Note that we did not specify a Persona in our Config class, so Hedra will utilize the Default persona. Had we explicitly specified a Persona as a class attribute of our Config class, Hedra would have used that Persona instead.

Hedra initializing a test session and booting up an embedded Statserve instance.

Next, Hedra will begin executing the test utilizing the fast-http engine we specified.

Hedra executing a test using the fast-http engine we specified in our Config class.

Hedra will execute tests in concurrent batches of the size we specified in our Config class, waiting the amount of time (in seconds) we likewise specified for each batch to complete before moving on to the next batch. Upon completion of a batch, Hedra will check to make sure it has not exceeded the total execution time we provided to the Config class, exiting the execution stage and returning non-aggregated results for processing during the results stage.

Hedra processing test results from actions executed during the execution stage.

During the results stage, Hedra will submit un-aggregated results to the "update" Reporter specified. Once all action results have been submitted, the "fetch" Reporter will then retrieve these aggregated results, passing them to the "submit" Reporter" for final storage/output.

By default, Hedra will utilize the Statserve Reporter for update, fetch, and submit. The "submit" Statserve reporter will output aggregated results to a JSON results.json file in the same directory in which the hedra command was run.

Upon completing the results stage, Hedra will then exit.

Hedra exiting after completing the test and submitting aggregated results.


Congratulations! You have run your first test! In summary, we wrote the test below in a file my_test.py:

from hedra.testing import (
    ActionSet,
    use,
    action,
    Test
)


class Config(Test):
    embedded_stats=True
    engine_type='fast-http'
    batch_size=8000
    batch_time=10
    total_time="00:01:00"


@use(Config)
class ExampleTest(ActionSet):

    @action('httpbin_get')
    async def httpbin_get(self):
        return await self.execute({
                'method': 'GET',
                'endpoint': '/get',
                'host': 'https://httpbin.org'
            })

Then ran the command:

hedra --code-filepath my_test.py

Upon which Hedra automatically imported and executed the test based upon the actions and configuration specified.

Clone this wiki locally