---
myst:
html_meta:
"description": ""
"property=og:description": ""
"property=og:title": ""
"keywords": ""
---
# Testing setup
Now let's take a moment (this chapter) to understand how Plone tests work and how they're set up.
To run tests in Plone you need three things:
- a test runner
- a testing setup
- tests
The plonecli tool already creates these things for us, so most of the configuration has already been done,
including some basic tests to use as a starting point.
```{note}
If you want to add tests from scratch into your addon or you want to update your testing environment, the best way is to create a new
package using plonecli with the same namespace, and then copy the generated files that you need into your addon.
```
## Test runner
A test runner is a script that collects all available tests and executes them.
Plone's test runner is a `zope.testing` script called "test", generated by a buildout recipe.
If we inspect the `base.cfg` file, we see a `test` part that uses this recipe:
```{literalinclude} _snippets/buildout.cfg
:language: ini
:lines: 46-51
```
We are setting some defaults when running tests:
\- `-s plonetraining.testing` means that we are executing all tests from a specific test suite (plonetraining.testing)
\- \`\`
--auto-color\`\` generates color console output with green and red reports for succeeding and failing tests
\- `--auto-progress` outputs the progress on the console
```{note}
In the previous chapter, we used plonecli to run tests, but that command is only a wrapper for the `bin/test` script.
```
```{note}
If we have a project with several addons and we want to test them all, we could add a similar configuration to our project's buildout.
In the `eggs` option we could list all packages that we want to test.
If we remove `'-s', 'plonetraining.testing'` from the defaults, all tests from packages listed in the `eggs` option will be
run by default.
```
## Testing setup
The testing setup for a Plone package is in a file called `testing.py`. It looks like this:
```{literalinclude} _snippets/testing.py
:language: python
```
There are three main pieces:
- a layer definition (PlonetrainingTestingLayer): a layer setup, a list of presets for testing environment (called fixtures), and making the packages available in the testing environment.
- a package fixture definition: this is the base setup for testing our package (PLONETRAINING_TESTING_FIXTURE).
- different test types: depending on our needs, we can use different test types, such as functional or integration tests.
plone.app.testing has a set of base Layers and fixtures that we use as starting point.
```{note}
We need to manually load all ZCML dependencies because autoinclude is disabled in plone.app.testing to preserve isolation.
```
## Setup and teardown hooks
plone.app.testing provides a set of hooks that we can use to perform several actions before a test or test suite runs (using setUp) or after it runs (using tearDown).
In `testing.py` file we usually use these hooks:
- setUpZope(self, app, configurationContext): to configure Zope (mostly importing ZCML profiles from the packages that we need to test) and its dependencies
- setUpPloneSite(self, portal): to configure the actual Plone site, for example installing the addon that we are going to test.
- tearDownPloneSite(self, portal): to clean up Plone when all tests end.
- tearDownZope(self, app): to clean up Zope when all tests end.
These will be called every time a test case uses that layer.
In each test case, we could have the following methods:
- setUp(self)
- tearDown(self)
We use these methods to define some common variables (for example, to access the portal object or the request), to pre-populate the site with content or to change permissions.
These methods are called for every single test.
## Tests
Tests are located in the `tests` folder.
In this folder you can create as many tests as you want, in one or more files. The only requirement is that the filenames should start with `test_`.
Tests can be grouped into test cases depending on the test type (unit, functional, integration or robot) and on the functionality that they are testing.
A test case defines which layer should be used, can set up the environment before test execution (using the `setUp` method) and can perform some actions after all tests have been executed (with the `tearDown` method).
plonecli creates a basic test case for testing that the addon installs correctly and registers its browserlayer.
## Assertions
A test is a method that does something (such as calling a method, instantiating a class, or executing more complex behavior) and checks that the result is what we expected.
These checks are made by `assertions`. They are statements that check if a generated value is the same as the expected one.
If an assertion fails in a test, the test itself fails. We can include as many assertions we want in a single test, and they must all succeed.
There are different types of assertions that we can use. For example:
```python
assertEqual(a, b)
a == b
assertTrue(x)
bool(x) is True
assertFalse(x)
bool(x) is False
assertIsNotNone(x)
x is not None
assertIn(a, b)
a in b
assertIsInstance(a, b)
isinstance(a, b)
assertRaises(exc, fun, *args, **kwds)
fun(*args, **kwds) raises exc
assertGreater(a, b)
a > b
assertGreaterEqual(a, b)
a >= b
```
Each assertion also has a "not" version:
```python
assertNotEqual(a, b)
a != b
assertNotIn(a, b)
a not in b
```