This will let us pass overrides for each test.
The instance fixture still provides our default instance:
def test_instance(instance): assert isinstance(instance.run_launcher, EcsRunLauncher)
But tests can also use the lower level instance_cm fixture to
customize the Dagster Instance (while still reaping the benefit of
ignoring the minutia of the stub_aws and metadata test setup):
def test_instance(instance_cm): with instance_cm({"container_name": "foo"}) as instance: assert isinstance(instance.run_launcher, EcsRunLauncher) assert instance.container_name == "foo"
The reason instance_cm returns a contextmanager rather than yielding
the instance directly is because when you yield a function that yields,
it returns a generator and not the thing being yielded. So callers would
need to call next(instance) to actually get their instance. Rough.
Another approach I looked at was using pytest parameterization:
@pytest.fixture def instance_config(): return {} @pytest.fixture def instance(stub_aws, metadata, instance_config): overrides = { "run_launcher": { "module": "dagster_aws.ecs", "class": "EcsRunLauncher", "config": {**(instance_config or {})}, } } with instance_for_test(overrides) as instance: yield instance def test_instance(instance): # If you don't parametrize, it uses the default `instance_config`. assert isinstance(instance.run_launcher, EcsRunLauncher) @pytest.mark.parametrize("instance_config", [{"container_name": "foo"}) def test_instance_parametrized(instance): assert isinstance(instance.run_launcher, EcsRunLauncher) assert instance.container_name == "foo"
While perhaps better adhering to pytest idioms, it's an inelegent
solution for two reasons:
- You can't easily parametrize the same fixture multiple times. So a test that needs multiple instances - each with their own config - is diffult to achieve.
- There's not an easy way for the parameter itself to source from a fixture (like if instead of {"container_name": "foo"}, we wanted {"container_name": foo_fixture}. This means we cede control of the fixture setup/teardown chain because we can't make our instance fixture depend on another fixture.