labthings_fastapi.testing
Test harnesses to help with writitng tests for things..
Attributes
Classes
A mock class that simulates a ThingServerInterface without the server. |
Functions
|
Create a |
|
Create a mock Thing instance, with some important attributes. |
|
Mock the slots of a thing created by create_thing_without_server. |
|
Use the dummy URL for function in the context variable. |
|
Manually connect a thing_slot. |
Module Contents
- labthings_fastapi.testing.Params
- labthings_fastapi.testing.ReturnType
- class labthings_fastapi.testing.MockThingServerInterface(name: str, class_name: str, settings_folder: str | None = None, enable_global_lock: bool = False)
Bases:
labthings_fastapi.thing_server_interface.ThingServerInterfaceA mock class that simulates a ThingServerInterface without the server.
This allows a
Thingto be instantiated but not connected to a server. The methods normally provided by the server are mocked, specifically:The
nameis set by an argument to__init__.start_async_task_soonsilently does nothing, i.e. the async function will not be run.The settings folder will either be specified when the class is initialised, or a temporary folder will be created.
get_thing_stateswill return an empty dictionary.
Initialise a ThingServerInterface.
- Parameters:
name – The name of the Thing we’re providing an interface to.
class_name – The name of the class of the Thing, used as part of the settings filename.
settings_folder – The location where we should save settings. By default, this is a temporary directory.
enable_global_lock – Whether to create a global lock object, to mock the server setting of the same name.
- _settings_tempdir: tempfile.TemporaryDirectory | None = None
- _settings_folder = None
- _global_lock
- _mocks: list[labthings_fastapi.thing.Thing] = []
- _class_name
- abstract _get_server() labthings_fastapi.server.ThingServer
Raise
NotImplementedErroras this is not mocked.- Returns:
the server to which we are connected.
- Raises:
NotImplementedError – because this function is not mocked.
- start_async_task_soon(async_function: Callable[Params, Awaitable[ReturnType]], *args: Any) concurrent.futures.Future[ReturnType]
Do nothing, as there’s no event loop to use.
This returns a
concurrent.futures.Futureobject that is already cancelled, in order to avoid accidental hangs in test code that attempts to wait for the future object to resolve. Cancelling it may cause errors if you need the return value.If you need the async code to run, it’s best to add the
Thingto alt.ThingServerinstead. Using a test client will start an event loop in a background thread, and allow you to use a realThingServerInterfacewithout the overhead of actually starting an HTTP server.- Parameters:
async_function – the asynchronous function to call.
*args – positional arguments to be provided to the function.
- Returns:
a
concurrent.futures.Futureobject that has been cancelled.
- publish(message: labthings_fastapi.message_broker.Message) None
Silently ignore published events.
- Parameters:
message – a message to publish.
- property settings_folder: str
The path to a folder where persistent files may be saved.
This will create a temporary folder the first time it is called, and return the same folder on subsequent calls.
- Returns:
the path to a temporary folder.
- property path: str
The path, relative to the server’s base URL, of the Thing.
A ThingServerInterface is specific to one Thing, so this path points to the base URL of the Thing, i.e. the Thing Description’s endpoint.
- get_thing_states() Mapping[str, Any]
Return an empty dictionary to mock the metadata dictionary.
- Returns:
an empty dictionary.
- property _action_manager: labthings_fastapi.actions.ActionManager
- Abstractmethod:
Raise an error, as there’s no action manager without a server.
- Raises:
NotImplementedError – always.
- property application_config: None
Return an empty application configuration when mocking.
- Returns:
None
- property global_lock: labthings_fastapi.global_lock.GlobalLock | None
Return a global lock.
- labthings_fastapi.testing.ThingSubclass
- labthings_fastapi.testing.create_thing_without_server(cls: type[ThingSubclass], *args: Any, settings_folder: str | None = None, mock_all_slots: bool = False, enable_global_lock: bool = True, **kwargs: Any) ThingSubclass
Create a
Thingand supply a mock ThingServerInterface.This function is intended for use in testing, where it will enable a
Thingto be created without a server, by supplying aMockThingServerInterfaceinstead of a realThingServerInterface.The name of the Thing will be taken from the class name, lowercased.
- Parameters:
cls – The
Thingsubclass to instantiate.*args – positional arguments to
__init__.settings_folder – The path to the settings folder. A temporary folder is used by default.
mock_all_slots – Set to True to create a
unittest.mock.Mockobject connected to each thing slot. It follows the default of the specified to the slot. So if an optional slot has a default ofNone, no mock will be provided.enable_global_lock – Whether a global lock should be provided.
**kwargs – keyword arguments to
__init__.
- Returns:
an instance of
clswith aMockThingServerInterfaceso that it will function without a server.- Raises:
ValueError – if a keyword argument called ‘thing_server_interface’ is supplied, as this would conflict with the mock interface.
- labthings_fastapi.testing.mock_thing_instance(spec: type[ThingSubclass]) ThingSubclass
Create a mock Thing instance, with some important attributes.
This provides
__name__,__module__, and_thing_server_interfaceproperties that work correctly, which is convenient when mockinglt.thing_slotconnections.- Parameters:
spec – the Thing subclass we’re mocking an instance of. Pass
lt.Thingif it doesn’t matter.- Returns:
a Mock instance that pretends to be an instance of
spec.
- labthings_fastapi.testing._mock_slots(thing: labthings_fastapi.thing.Thing) None
Mock the slots of a thing created by create_thing_without_server.
- Parameters:
thing – The thing to mock the slots of.
- Raises:
TypeError – If this was called on a Thing with a real ThingServerInterface
- labthings_fastapi.testing.use_dummy_url_for() collections.abc.Iterator[None]
Use the dummy URL for function in the context variable.
- labthings_fastapi.testing.manually_connect_thing_slot(host: labthings_fastapi.thing.Thing, slot_name: str, target: labthings_fastapi.thing.Thing | collections.abc.Sequence[labthings_fastapi.thing.Thing]) None
Manually connect a thing_slot.
This will accept either a single
Thinginstance or a sequence ofThinginstances. IfMockinstances are used, note that they must pass anisinstancetest, so should use thespecargument to specify the correct class for thething_slotbeing mocked. Mock instances must also provide a uniquenameattribute.- Parameters:
host – the
Thingon which the slot is defined.slot_name – the name of the
thing_slot.target – the
Thingor sequence of Things it should be connected to. If a sequence of multiple Thing are passed, their names are used to create a mapping.
- Raises:
KeyError – if multiple targets are specified, but they do not have unique names.