Decorators
Scenario
To mark a function as a Cicada scenario, use the scenario decorator. Remember to attach it to the engine.
Example
from cicadad.core.decorators import scenario
from cicadad.core.engine import Engine
engine = Engine()
@scenario(engine)
def hello_world():
assert 2 + 2 == 4
API
def scenario(engine: Engine, name: str = None, raise_exception: bool = True):
"""Mark a function as a scenario
Args:
engine (Engine): Engine to attach scenario to
name (str, optional): Name to give to scenario. Defaults to function name if None.
raise_exception (bool): Raise exception if user loop fails.
"""
User Loop
Override the user loop of a scenario.
Example
from cicadad.core.decorators import scenario, user_loop
from cicadad.core.scenario import iterations_per_second_limited
...
@scenario(engine)
@user_loop(iterations_per_second_limited(4))
def hello_world():
assert 2 + 2 == 4
API
def user_loop(user_loop_fn: UserLoopFn):
"""Function to handle how the user function is run
Args:
user_loop_fn (UserLoopFn): User defined user loop function
"""
Users Per Container
Sets number of users that can fit inside a single user container. Allows more users to run with fewer resources.
Example
from cicadad.core.decorators import scenario, users_per_container
...
@scenario(engine)
@users_per_container(200)
def hello_world():
assert 2 + 2 == 4
API
def users_per_container(users_per_container: int):
"""Sets how many users can fit inside a single user manager container.
Default is 50 users per container
Args:
users_per_container (int): Number of users to fit in a single container
"""
Load Model
Override the load model function for a scenario.
Example
from cicadad.core.decorators import scenario, load_model
from cicadad.core.scenario import n_seconds
...
@scenario(engine)
@load_model(n_seconds(30, 10))
def hello_world():
assert 2 + 2 == 4
API
def load_model(load_model_fn: LoadModelFn):
"""Function to handle how scenario is run with regards to starting users and
administering work
Args:
load_model_fn (LoadModelFn): User defined load model function
"""
Dependency
Mark a scenario as dependent on another scenario passing.
Example
from cicadad.core.decorators import scenario, dependency
...
@scenario(engine)
def test_a():
assert 2 + 2 == 4
@scenario(engine)
@dependency(test_a)
def test_b():
assert 3 + 3 == 6
API
def dependency(dep: Scenario):
"""Set a scenario as a dependency for this scenario to run
Args:
dep (Scenario): Scenario this function is dependent on being successful
"""
Result Aggregator
Add a function to aggregate results gathered during scenario.
Example
from cicadad.core.decorators import scenario, result_aggregator
...
def agg(last_agg, latest_results):
if last_agg is None:
total = 0
else:
total = last_agg
return total + sum(r.output for r in latest_results)
@scenario(engine)
@result_aggregator(agg)
def hello_world():
assert 2 + 2 == 4
return 1
API
def result_aggregator(aggregator_fn: ResultAggregatorFn):
"""Transform previous aggregate and list of results into an aggregated
single result. Called by load model function
Args:
aggregator_fn (ResultAggregatorFn): Aggregator function
"""
Result Verifier
Add a function to verify results and add error strings for results gathered during scenario.
Example
from cicadad.core.decorators import scenario, result_verifier
...
def verifier(latest_results):
return [
f"* {str(result.exception)}"
for r in latest_results
if r.exception is not None
]
@scenario(engine)
@result_verifier(verifier)
def hello_world():
assert ..., "expected x but got y"
API
def result_verifier(verifier_fn: ResultVerifierFn):
"""Create error messages for errors found in a list of results. Called by
load model function
Args:
verifier_fn (ResultVerifierFn): Verifier function
"""
Output Transformer
Transform final aggregate to be saved as scenario output after load model completes.
Example
from cicadad.core.decorators import scenario, result_aggregator, output_transformer
...
def agg(last_agg, latest_results):
if last_agg is None:
total = 0
else:
total = last_agg
return total + sum(r.output for r in latest_results)
def transform(agg):
return f"Total: {agg}"
@scenario(engine)
@result_aggregator(agg)
@output_transformer(transform)
def hello_world():
assert 2 + 2 == 4
return 1
API
def output_transformer(transformer_fn: OutputTransformerFn):
"""Transform the aggregated result of the scenario after load model is
called
Args:
transformer_fn (OutputTransformerFn): Transformer function
"""
Metrics Collector
Adds function to scenario to parse latest results and send metrics
Example
from datetime import datetime
from cicadad.core.decorators import scenario, metrics_collector, console_metric_displays
from cicadad.metrics.console import (
console_collector,
console_count,
console_latest,
console_stats,
)
...
def extract_ms(latest_results):
return [
float(result.output) for result in latest_results if result.exception is None
]
@scenario(engine)
@metrics_collector(console_collector("stats", extract_ms))
@metrics_collector(console_collector("latest", extract_ms))
@metrics_collector(console_collector("count", extract_ms))
@console_metric_displays(
{
"stats": console_stats(),
"latest": console_latest(),
"count": console_count(),
}
)
def hello_world():
start = datetime.now()
assert 2 + 2 == 4
end = datetime.now()
return (end - start).total_seconds()
API
def metrics_collector(collector: MetricCollector):
"""Add a collector function to parse and send metrics from scenario.
Args:
collector (MetricCollector): Collector function
"""
Console Metric Displays
Display metric in the live metrics sidebar during a test.
Example
See example in Metrics Collector.
API
def console_metric_displays(displays: ConsoleMetricDisplays):
"""Sets map of names to metric displays for scenario.
Args:
displays (ConsoleMetricDisplays): Map of names to console metric display getters
"""
Tag
Add a tag to scenario so it can be optionally excluded during test run.
Example
from cicadad.core.decorators import scenario, tag
...
@scenario(engine)
@tag("foo")
def hello_world():
assert 2 + 2 == 4
API
def tag(tag: str):
"""Add a tag to a scenario. Tags allow for a test run to only cover certain
scenarios.
Args:
tag (str): Tag name to add to scenario
"""