Testing the Resource

Concourse Tools contains a number of functions for easier testing.

You can take advantage of the class-based paradigm in Concourse Tools to test your resource class as a standard Python object. You can call the functions with specific inputs to check that they are turning the correct outputs. However, this does limit your ability to mock the script environment when your code relies on external factors.

Using Test Wrappers

Multiple test wrappers are available:

Test Class

Input / Output

Executed As

SimpleTestResourceWrapper

Python

Resource class

JSONTestResourceWrapper

JSON

Main scripts

ConversionTestResourceWrapper

Python

Main scripts

FileTestResourceWrapper

JSON

External scripts

FileConversionTestResourceWrapper

Python

External scripts

DockerTestResourceWrapper

JSON

Docker container

DockerConversionTestResourceWrapper

Python

Docker container

Base Wrapper

All of the above inherit from TestResourceWrapper:

class concoursetools.testing.TestResourceWrapper(directory_dict=None, one_off_build=False, instance_vars=None, **env_vars)[source]

A simplistic resource wrapper designed to reduce test code.

The most accurate way to test your resource class is to invoke a test wrapper. Each one inherits from this class, and exposes a method for each of the three resource operations: fetch_new_versions(), download_version() and publish_new_version().

Tip

Make use of the capture_debugging() and capture_directory_state() methods to capture the debugging output and directory state changes respectively.

Parameters:
  • directory_dict (dict[str, Any] | None) – The initial state of the resource directory. See TemporaryDirectoryState

  • one_off_build (bool) – Set to True if you are testing a one-off build.

  • instance_vars (dict[str, str] | None) – Pass optional instance vars to emulate an instanced pipeline.

  • env_vars (str) – Pass additional environment variables, or overload the default ones.

Caution

Each wrapper will use different signatures for these methods to reflect the different ways that inputs can be passed to the inner resource. Make sure to select the wrapper which works best for how you wish to test your resource.

Example:
>>> from tests.resource import TestResource, TestVersion
>>> resource = TestResource("git://some-uri")
>>> wrapper = SimpleTestResourceWrapper(resource)
>>> version = TestVersion("61cbef")
>>> with wrapper.capture_debugging() as debugging:
...     with wrapper.capture_directory_state() as directory_state:
...         _, metadata = wrapper.download_version(version)
...     assert directory_state.final_state == {"README.txt": "Downloaded README for ref 61cbef.\n"}
...     assert metadata == {"team_name": "my-team"}
...     assert debugging == "Downloading.\n"
abstractmethod fetch_new_versions()[source]

Fetch new versions of the resource.

Return type:

object

abstractmethod download_version()[source]

Download a version and place its files within the resource directory in your pipeline.

Return type:

object

abstractmethod publish_new_version()[source]

Update a resource by publishing a new version.

Return type:

object

capture_debugging()[source]

Redirect the resource debugging output within a context manager into a variable.

Seealso:

This is done using an instance of StringIOWrapper. A call is made to clear() when the context manager is opened.

Note

The output is directed regardless of whether this is used.

Return type:

Generator[StringIOWrapper]

capture_directory_state(starting_state=None)[source]

Open a context manager to expose the internal state of the resource.

Parameters:

starting_state (dict[str, Any] | None) – Set the starting state of the directory. If not set this defaults to the starting state as passed to the instance via the directory_dict parameter.

Seealso:

This is done using an instance of TemporaryDirectoryState.

Return type:

Generator[TemporaryDirectoryState]

Note

It is impossible to call the fetch_new_versions() method from within this context manager.