71 lines
3.3 KiB
Markdown
71 lines
3.3 KiB
Markdown
# Python Language Host Tests
|
|
|
|
The tests in this directory test the language host directly by posing
|
|
as the engine and running programs in the same context that they would
|
|
be run by the CLI. Programs run by these tests can create resources,
|
|
read resource, invoke data sources, and generally do anything that
|
|
a Pulumi program can do.
|
|
|
|
Language host tests provide a program to be run and an implementation
|
|
of the `LanghostTest` class, which provides implementations for the
|
|
four resource monitor endpoints that the language host speaks to:
|
|
|
|
* `invoke`, for invoking data sources,
|
|
* `read_resource`, for reading existing resources,
|
|
* `register_resource`, for creating new resources,
|
|
* `register_resource_outputs`, for registering outputs on component resources
|
|
|
|
Classes deriving from `LanghostTest` can override any of these methods
|
|
to provide custom test functionality. This is commonly used to perform assertions
|
|
or place the language host in unexpected situations.
|
|
|
|
## Adding a new test
|
|
|
|
To add a new language host test, you can:
|
|
|
|
1. Create a new directory in this directory with the name of your test
|
|
2. Place an `__init__.py` and `__main__.py` in this directory. `__init__.py` convinces
|
|
Python that this directory is a module, while `__main__.py` indicates to Python that
|
|
this module is runnable.
|
|
3. Write your Pulumi program in `__main__.py`. If you want to do assertions, use the `assert`
|
|
keyword to do so.
|
|
4. Add a test file, which can have any name. In this test file you'll want to provide a
|
|
subclass of `LanghostTest` that drives your test. An example minimal test would be something
|
|
like this:
|
|
|
|
```python
|
|
from os import path
|
|
from ..util import LanghostTest
|
|
|
|
|
|
class EmptyTests(LanghostTest):
|
|
def test_empty(self):
|
|
self.run_test(
|
|
program=path.join(self.base_path(), "empty"), # If your test is in the empty/ subdirectory
|
|
expected_resource_count=0) # Assert there are 0 resource registrations
|
|
```
|
|
|
|
Your class can have any number of `test_*` methods in them. Language host tests are launched by
|
|
invoking the `run_test` method inherited from `LanghostTest`. `run_test` accepts the following
|
|
keyword arguments:
|
|
|
|
* `project` - The name of the project that will be exposed to the running program
|
|
* `stack` - The name of the stack that will be exposed to the running program
|
|
* `program` - A path to the program to be run, relative to the working directory.
|
|
* `pwd` - The working directory to use.
|
|
* `args` - Command-line arguments to pass to the program.
|
|
* `config` - A dict of configuration keys and values to pass to the program.
|
|
* `expected_resource_count` - The number of resources this test is expected to register.
|
|
* `expected_error` - If non-None, the *exact* error text that is expected to be received.
|
|
* `expected_stderr_contains` - If non-None, asserts that the given substring exists in stderr
|
|
|
|
If `expected_error` is None, the expected error is asserted to be the empty string.
|
|
|
|
Note that your test method must begin with `test_*`, since this is how Python discovers what
|
|
tests to run.
|
|
|
|
One additional thing to note is that this test harness explicitly ignores the registration
|
|
of the top-level Stack resource, `pulumi:pulumi:Stack`, because it is annoying to write tests around.
|
|
All expected resource counts do not count this resource as a registration and overridden resource monitor
|
|
methods will never see a registration for `pulumi:pulumi:Stack.`
|
|
|