Skip to content

Commit 0b37989

Browse files
committed
Tidy unit-tests.md
1 parent 9185cf2 commit 0b37989

File tree

1 file changed

+57
-84
lines changed

1 file changed

+57
-84
lines changed
Lines changed: 57 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,40 @@
11
---
22
myst:
33
html_meta:
4-
"description": ""
5-
"property=og:description": ""
6-
"property=og:title": ""
7-
"keywords": ""
4+
"description": "How to write basic unit tests for content types in Plone"
5+
"property=og:description": "How to write basic unit tests for content types in Plone"
6+
"property=og:title": "How to write basic unit tests for content types in Plone"
7+
"keywords": "Plone, content types, unit tests"
88
---
99

1010
# Unit tests
1111

12-
**Writing simple unit tests**
12+
This chapter describes how to write basic unit tests for content types.
1313

14-
As all good developers know, automated tests are very important!
15-
If you are not comfortable with automated testing and test-driven
16-
development, you should read the [Plone testing tutorial].
17-
In this section, we will assume you are familiar with Plone testing basics,
18-
and show some tests that are particularly relevant to our example types.
14+
As all good developers know, automated tests are very important.
15+
If you are not comfortable with automated testing and test-driven development, you should read the [Plone testing tutorial](https://5.docs.plone.org/external/plone.testing/docs/index.html).
16+
In this section, we will assume you are familiar with Plone testing basics, and show some tests that are particularly relevant to our example types.
1917

2018
Firstly, we will add a few unit tests.
21-
Recall that unit tests are simple tests for a particular function or method,
22-
and do not depend on an outside environment being set up.
23-
As a rule of thumb, if something can be tested with a simple unit test, do
24-
so, because:
25-
26-
- Unit tests are quick to write.
27-
- They are also quick to run.
28-
- Because they are more isolated, you are less likely to have tests
29-
that pass or fail due to incorrect assumptions or by luck.
30-
- You can usually test things more thoroughly and exhaustively with
31-
unit tests than with (slower) integration tests.
32-
33-
You’ll typically supplement a larger number of unit tests with a smaller
34-
number of integration tests, to ensure that your application’s correctly
35-
wired up and working.
36-
37-
That’s the theory, at least. When we’re writing content types, we’re
38-
often more interested in integration test, because a type schema and FTI
39-
are more like configuration of the Plone and Dexterity frameworks than
40-
imperative programming.
41-
We can’t “unit test” the type’s schema interface, but we can and should test
42-
that the correct schema is picked up and used when our type is installed.
43-
We will often write unit tests (with mock objects, where required) for
44-
custom event handlers, default value calculation functions and other
45-
procedural code.
46-
47-
In that spirit, let’s write some unit tests for the default value
48-
handler and the invariant in `program.py`.
49-
We’ll add the directory `tests`, with an `__init__.py` and a file
50-
`test_program.py` that looks like this:
19+
Recall that unit tests are simple tests for a particular function or method, and do not depend on an outside environment being set up.
20+
As a rule of thumb, if something can be tested with a simple unit test, do so for the following reasons.
5121

52-
```
22+
- Unit tests are quick to write.
23+
- They are also quick to run.
24+
- Because they are more isolated, you are less likely to have tests that pass or fail due to incorrect assumptions or by luck.
25+
- You can usually test things more thoroughly and exhaustively with unit tests than with (slower) integration tests.
26+
27+
You'll typically supplement a larger number of unit tests with a smaller number of integration tests, to ensure that your application's correctly wired up and working.
28+
29+
That's the theory, at least.
30+
When we write content types, we're often more interested in integration tests, because a type schema and FTI are more like configuration of the Plone and Dexterity frameworks than imperative programming.
31+
We can't "unit test" the type's schema interface, but we can and should test that the correct schema is picked up and used when our type is installed.
32+
We will often write unit tests (with mock objects, where required) for custom event handlers, default value calculation functions and other procedural code.
33+
34+
In that spirit, let's write some unit tests for the default value handler and the invariant in {file}`program.py`.
35+
We'll add the directory `tests`, with an `__init__.py` and a file {file}`test_program.py` as shown.
36+
37+
```python
5338
import unittest
5439
import datetime
5540

@@ -114,58 +99,46 @@ def test_suite():
11499
return unittest.defaultTestLoader.loadTestsFromName(__name__)
115100
```
116101

117-
This is a simple test using the Python standard library’s `unittest`
118-
module. There are a few things to note here:
119-
120-
- We have created a dummy class to simulate a `Program` instance.
121-
It doesn’t contain anything at all, but we set some attributes onto it
122-
for certain tests.
123-
This is a very simple way to do mocks.
124-
There are much more sophisticated mock testing approaches, but starting
125-
simple is good.
126-
- Each test is self contained.
127-
There is no test layer or test case setup/tear-down.
128-
- We use the `defaultTestLoader` to load all test classes in the module
129-
automatically.
130-
The test runner will look for modules in the `tests`
131-
package with names starting with `test` that have a `test_suite()`
132-
method to get test suites.
133-
134-
To run the tests, we can do:
135-
136-
```console
137-
$ ./bin/test example.conference
102+
This is a test using the Python standard library's `unittest` module.
103+
There are a few things to note here:
104+
105+
- We have created a dummy class to simulate a `Program` instance.
106+
It doesn't contain anything at all, but we set some attributes onto it for certain tests.
107+
This is a very simple way to do mocks.
108+
There are much more sophisticated mock testing approaches, but starting simple is good.
109+
- Each test is self contained.
110+
There is no test layer or test case setup or tear down.
111+
- We use the `defaultTestLoader` to load all test classes in the module automatically.
112+
The test runner will look for modules in the `tests` package with names starting with `test` that have a `test_suite()` method to get test suites.
113+
114+
To run the tests, use the following command.
115+
116+
```shell
117+
./bin/test example.conference
138118
```
139119

140120
Hopefully it should show five passing tests.
141121

142-
:::{note}
143-
This uses the testrunner configured via the `[test]` part in our
144-
`buildout.cfg`.
145-
This provides better test reporting and a few more advanced options
146-
(like output colouring).
147-
We could also use the built-in test runner in the `instance` script,
148-
e.g. with `./bin/instance test -s example.conference`.
149-
:::
122+
```{note}
123+
This uses the testrunner configured via the `[test]` part in our `buildout.cfg`.
124+
This provides better test reporting and a few more advanced options, such as output coloring.
125+
We could also use the built-in test runner in the `instance` script, for example, with `./bin/instance test -s example.conference`.
126+
```
150127

151-
To run just this test suite, we can do:
128+
To run just this test suite, use the following command.
152129

153-
```console
154-
$ ./bin/test example.conference -t TestProgramUnit
130+
```shell
131+
./bin/test example.conference -t TestProgramUnit
155132
```
156133

157-
This is useful when we have other test suites that we don’t want to run,
158-
e.g. because they are integration tests and require lengthy setup.
134+
This is useful when we have other test suites that we don't want to run when they are integration tests and require lengthy setup.
159135

160-
To get a report about test coverage, we can run:
136+
To get a report about test coverage, we can run the following command.
161137

162-
```console
163-
$ ./bin/test example.conference --coverage
138+
```shell
139+
./bin/test example.conference --coverage
164140
```
165141

166-
Test coverage reporting is important. If you have a module with low test
167-
coverage, it means that your tests do not cover many of the code paths
168-
in those modules, and so are less useful for detecting bugs or guarding
169-
against future problems. Aim for 100%.
170-
171-
[plone testing tutorial]: /external/plone.app.testing/docs/source/index
142+
Test coverage reporting is important.
143+
If you have a module with low test coverage, it means that your tests do not cover many of the code paths in those modules, and so are less useful for detecting bugs or guarding against future problems.
144+
Aim for 100% coverage.

0 commit comments

Comments
 (0)