Features Listο
This section provides an overview of FireFly features for both Autotests and Scripts, along with code examples and report integration.
π§ͺ Auto Test Featuresο
Stagesο
Each test can consist of the following stages (all optional):
Group Setup β executed once for all tests in a class.
Use this for shared resources like DB connections or sessions (non-stateful).Setup β executed before each test iteration.
Call β the actual test iteration.
Teardown β executed after each iteration, regardless of the result.
Group Teardown β executed after all iterations are complete.
Example:ο
class StagesExample(TestAbs):
all_tests_in_class_shared_resource: str | None = None
def __init__(self):
self.one_test_iteration_resource: str | None = None
@classmethod
async def group_setup(cls):
cls.all_tests_in_class_shared_resource = "Shared setup"
async def setup(self, **test_params):
self.one_test_iteration_resource = "Iteration setup"
@params([
dict(iteration_name="First iteration"),
dict(iteration_name="Second iteration"),
])
async def test_example(self):
print(self.all_tests_in_class_shared_resource)
print(self.one_test_iteration_resource)
async def teardown(self, **test_params):
self.one_test_iteration_resource = None
@classmethod
async def group_teardown(cls):
cls.all_tests_in_class_shared_resource = None
Iterationsο
Each test must define at least one iteration using the @params decorator.
@params([
dict(iteration_name="First iteration"),
dict(iteration_name="Second iteration"),
])
async def test_example(self):
pass
You can also pass parameters:
@params([
dict(iteration_name="First", a=1, b="b"),
dict(iteration_name="Second", a=2),
])
async def test_success(self, a: int, b: str | None = None):
pass
π‘ All values must be JSON-serializable.
Iteration parameters are shown in the report under the βParametersβ tab.
Auto-Generated Iterationsο
Use @params_product to create combinations automatically:
@params_product(
iteration_name="{client_type} client with {account_type} account",
account_type=["live", "demo"],
client_type=["Individual", "Corporate"]
)
async def test_example(self, client_type: str, account_type: str):
pass
Inheritanceο
FireFly supports class inheritance (including multiple inheritance), which is useful for sharing setup/teardown logic.
class MyServiceBaseTest(TestAbs):
def __init__(self):
self.example_resource: str | None = None
async def setup(self, **test_params):
self.example_resource = "test"
async def teardown(self, **test_params):
self.example_resource = None
class Test1(MyServiceBaseTest):
@params([dict(iteration_name="First iteration")])
async def test_example(self):
print(self.example_resource)
All stages from base classes are executed in reverse MRO order.
Descriptionsο
Add a docstring inside test methods to make them easier to understand in reports:
@params([dict(iteration_name="First")])
async def test_success(self):
"""
This test verifies user login with valid credentials.
"""
pass
Stepsο
Use step() to structure your test and make the report more informative.
@params([dict(iteration_name="First")])
async def test_success(self):
async with step("Start"):
async with step("Continue"):
pass
Steps can be nested and used in any test stage or method.
RunConfigο
Tests can expose custom configuration through RunConfig class:
@register()
class RunConfigExample(TestAbs):
class RunConfig:
string_field = StringField(label="Some String")
number_field = NumberField(label="Some Number")
switch_field = SwitchFiled(label="Some Switch")
checkbox_field = CheckboxFiled(label="Some Checkbox")
autocomplete_field = AutocompleteFiled(
label="Choose Option", options=["First", "Second", "Third"]
)
@params([dict(iteration_name="With config")])
async def test_success(self):
print(self.RunConfig.string_field.value)
All values are recorded in the report for reproducibility.
Environment Variablesο
You can access environment variables using the env object:
async with step("Print env variable"):
print(env.application_url)
All used variables are saved in the report under Environment Used tab.
Assetsο
Save files (logs, screenshots, etc.) into reports via AssetsHelper.
@register()
class AssetHelperExample:
assets_helper: Optional[AssetsHelper] = None
@classmethod
async def group_setup(cls):
cls.assets_helper = AssetsHelper()
@params([dict(iteration_name="Attach file")])
async def test_success(self):
await self.assets_helper.add_text("log.txt", b"Some log")
@classmethod
async def group_teardown(cls):
await cls.assets_helper.close_connection()
Generated Parametersο
To make dynamic data visible in reports, use add_info_to_test_generated_params():
add_info_to_test_generated_params("random_email", f"user_{randint(100)}@mail.com")
Warningsο
If something goes wrong, but the test shouldnβt fail β add a warning:
add_warning_to_test("Service responded with error on first attempt")
Errorsο
Unhandled exceptions in tests are captured and shown in the report, with full traceback.
Comparisonsο
FireFly provides helper methods based on Pydantic:
compare_pydantic_models(real=actual, expected=expected)
It highlights differences in the report.
Other helpers include:
ApproximatelyEqual,ApproximatelyDateEqualFromProtobufModelBCryptPasswordEqualall_optionalCamelCaseModel,PascalCaseModeletcβ¦
βοΈ Script Runner Featuresο
Dynamic Parametersο
Use type annotations to declare script parameters:
from enum import StrEnum
from src.modules.script_runner.register import register
class MyEnum(StrEnum):
a = "a"
b = "b"
@register
async def my_script(
some_float: float,
some_str_enum: MyEnum,
some_date_one: date,
some_file: BytesIO,
some_date_two: pendulum.Date = pendulum.Date(year=2023, month=11, day=11),
some_string: str = "test",
some_int: int = 10,
some_bool: bool = True,
):
pass
Required in UI if no default is provided.
Descriptionο
Add a docstring to explain the scriptβs behavior:
@register
async def my_script():
"""
Cleans up unused client records in test DB.
"""
Loggingο
Use log() to track progress inside scripts:
@register
async def example():
for i in range(3):
await log(f"Step {i}")
If called inside step(), logs for entering/exiting each step will appear automatically.
Smart Result Formattingο
FireFly auto-formats results:
Type |
UI Display |
|---|---|
|
Two-column table |
List of dicts/models |
Multi-row table with headers |
FileResult/List of FileResult |
File response |
Other |
Stringified output |
Environment Variablesο
Access them just like in autotests:
await log(env.db_password)
All variables used are shown in report + history.
Error Handlingο
Uncaught exceptions are recorded. If using ExceptionGroup, all grouped exceptions will be shown separately in the report.
Class-Based Scriptsο
Scripts can also be written as classes:
@register
class ThirdScript(ScriptClassAbs):
def __init__(self):
self.counter = 0
async def run(self, value: str):
await log(value)
for i in range(5):
self.counter += 1
await log(self.counter)
Must inherit from
ScriptClassAbsMust define
run()as async method
All script features work the same way.