1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
|
# Tutorial: Functional testing of Debian packages
This is a transcription of a Debconf15 talk, which you might want to
[watch](http://meetings-archive.debian.net/pub/debian-meetings/2015/debconf15/Tutorial_functional_testing_of_Debian_packages.webm)
(WebM format, 469MB).
Do you maintain a Debian package? This tutorial covers implementing autopkgtests
for your Debian packages.
Before covering how to get your package(s) running under autopkgtest, let's
cover a few preliminary topics. If you already have knowledge about the
topics below, feel free to skip to the `Adding tests` section of the tutorial.
## What is autopkgtest?
autopkgtest establishes a standard interface to define and run "as-installed"
tests of packages, i.e. the testing of packages in context as close as possible
to a Debian system where the packages subject to testing are properly installed.
## The DEP-8 specification
Information on the DEP-8 specification is available from http://dep.debian.net/deps/dep8.
There are two basic elements of this specification:
* The `Source` stanza of your Debian control file declaring that the package has
a testsuite.
* An extra control file in `debian/tests/`
### Declaring that a package has a testsuite
This can be done by adding a `Testsuite` field with `autopkgtest` as the value.
**debian/control**
```
Source: foo
[...]
Testsuite: autopkgtest
```
You can also use other values. One such value is autopkgtest-pkg-`language`.
This helps to identify how to run the tests in the package.
### Adding the extra control file
Once you have the debian/control file completed, you need to create an extra
control file in debian/tests (i.e. debian/tests/control).
In this file, you list your tests for the package.
**debian/tests/control**
```
Tests: foo bar baz
```
In this example, there are three tests declared and `foo`, `bar`, and `baz` must
be executables in debian/tests/.
There can also be extra fields in the debian/tests/control file.
You can use Depends:
```
Depends: @, test-tool
```
The `@` symbol means all the binaries of this source package. So, when the testbed
is prepared, all of the binaries will be installed in addition to the ones you declare.
In this case, all the binaries will be installed and some test tool will be installed
to run tests.
# Adding tests
## Tests with different characteristics
You can also have multiple tests with different characteristics.
To do this, multiple stanzas must be in the control file.
```
Tests: test-my-package
Depends: @, test-tool
Tests: smoke-test
```
In this case, there is one test program that needs a given test tool and
some smoke test that does not need anything besides the binary.
If nothing is declared, the Depends values are assumed to be binaries.
`@` will be the default value.
If you just need your binaries, you do not need to declare anything.
### Build dependencies
Build dependencies are also needed to run tests. Let's assume you want
to run an upstream test suite which uses x unit framework or other frameworks.
You can use that framework and your build dependencies.
```
Test: upstream-tests
Depends: @, @builddeps@
```
### Additional Requirements
Restrictions can also be specified on the tests. It is an additional requirement.
Let's look at an example.
```
Tests: break-the-world
Restrictions: breaks-testbed
```
The above states that the tests break the testbed. It puts the testbed into a state
that is not going to work when you run a second test on it.
In this case, there is only one test. If you have more than one test though, and
`breaks-testbed` is specified you will instantiate a new testbed for each test.
Otherwise, you just use the same one.
*Note: If you run these tests outside a VM or a container, the virtualization driver
will skip these tests. On your main system, especially as root, these tests are going
to be skipped so that your main system is not broken.*
### Tests that need root access
It can also be specified that the tests need root access. You may need to think
twice before doing this.
```
Tests: play-with-danger
Restrictions: needs-root
```
### Allowing output to standard error (stderr)
If the tests output anything on the standard error stream, then it's considered
a failure. To overcome this, `allow-stderr` needs to be declared in the Restrictions
header.
```
Tests: complain-but-succeed
Restrictions: allow-stderr
```
### Isolating tests with a container
The level of isolation you want from your host system can also be specified.
If `isolation-container` is declared in the Restrictions header, then the only
things as isolated as a container or more will be able to run the tests.
So, if you want to mess with system services by stopping, starting, etc
services, you do not want that to run in your host system, because that will
cause problems.
```
Tests: mess-with-services
Restrictions: isolation-container
```
### Isolating tests with a virtual machine
Tests can also be isolated to running in a virtual machine. This is specified by
declaring `isolation-machine`. This provides even more isolation than a container.
This can be useful for loading kernel modules and test things related to the
kernel.
```
Tests: mess-with-kernel
Restrictions: isolation-machine
```
## Tools
### sadt
sadt, which is part of devscripts, runs tests from the root of a source package
in the current directory on the current system.
It is somewhat limited since it will possibly skip some tests but is useful as a
first step.
### autopkgtest
autopkgtest can run tests from the current directory, the DSC, a changefile,
or pass additional binary DEBs.
```
$ autopkgtest [options] -- [virtualization args]
```
Two dashes are passed to autopkgtest after the input options followed by virtualization options
which specifies which virtual environment to use to run the tests.
Let's look at a basic example:
```
$ autopkgtest . -- null
```
The command above runs the tests from the source package at the current directory, on the
current system. Note the `null` argument for the virtualization.
Let's look at an example that uses virtualization:
```
$ autopkgtest -u debci /path/to/foo_1.2.3-1_amd64.changes -- lxc --sudo autopkgtest-unstable-amd64
```
The command above runs tests from the source referenced by the `changes` file, using
its binaries, under a user called `debci`. The tests are being run in a `lxc` session
based on the `autopkgtest-unstable-amd64` base container.
You can also use other virtualization tools, such as `qemu`, and `ssh`. See
autopkgtest-virt-\* man pages for more information.
# Functional tests by example (plus tips and tricks)
Let's look at a couple of package examples that have autopkgtest support.
## Package: pinpoint
In pinpoint's `debian/tests/control` file, the following is declared:
```
Tests: smoke-tests
Depends: @, file, shunit2
```
As you can see, pinpoint has a very simple test definition. It has a simple test
script called `smoke-tests` and it uses its own binaries (noted by the `@`), file,
and shunit2.
### `Tip 1: Use shunit2`
The smoke-tests file contains the following:
```
#!/bin/sh
exec 2>&1
set -e
test_pdf_output() {
pdf=$AUTOPKGTEST_TMP/introduction.pdf
pinpoint -o $pdf introduction.pin
assertEquals "application/pdf" "$(file --mime-type --brief $pdf)"
}
test_pdf_output_with_empty_background() {
pdf=$AUTOPKGTEST_TMP/global-background.pdf
pin=$AUTOPKGTEST_TMP/global-background.pin
cat > $pin <<EOF
[]
--
test
EOF
pinpoint -o $pdf $pin
assertEquals "application/pdf" "$(file --mime-type --brief $pdf)"
}
. shunit2
```
Then, we can run it with sadt or autopkgtest.
Note: `sadt` hides output and `autopkgtest . -- null` gives full output.
# Miscellaneous
In addition to https://ci.debian.net, CI data is also available in the
[UDD/DMD](https://udd.debian.org/dmd/),
[DDPO](https://qa.debian.org/developer.php), and
[package tracker](https://tracker.debian.org/).
|