Status

Contents

Introduction

Discuss ways to automatically check certain package properties which we regard as essential.

Purpose, Scope and Use Cases

Currently it is possible to upload packages which do not work at all, can disrupt the packaging system, are uninstallable, or have a broken build system. We want to introduce a set of universally applicable tests that reject such packages before they irritate anyone. To the extent possible, a package should also be able to check its own functionality to make regressions immediately visible.

Testing environment use cases

Test case possibilities

Overall Design

Testing of installed packages

We will create the following new machinery:

Initially, all but the package-specific tests will be in a single test package.

There are two main new interfaces here:

Virtualisation

To test a package it must be installed (and often, removed again) for testing. Its installation or operation might alter the system or data in other ways.

For other than the most ad-hoc testing by a knowledgeable expert, there has to be a separate testbed for this purpose. Ideally, the testbed would be virtualised.

There are a fair variety of virtualisation systems which differ in maturity, intrusiveness into the hosting system/hardware, features, etc. We are interested in the following features:

Approaches or part-approaches that seem plausible include:

There is a lot of activity in many of these projects, so their capabilities are changing. And, different approaches make sense in different contexts (local testing, launchpad autotest, etc.). So we introduce an abstraction interface which we'll provide at least one low-impact sample implementation of.

Initially we will implement a regime based on chroot (for encapsulation), inotify (if feasible, for getting lists of changed files etc.) and lvm/dm snapshots (for reverting the fs efficiently).

Interface Design

Tests/metadata

NOTE that this specification is no longer the master copy. The primary copy is in autopkgtest/doc/README.package-tests. DO NOT EDIT this section in the wiki; it is retained here only for historical interest.

DRAFT - this section needs discussing with debian-policy. We want to share this test infrastructure with Debian and other distros to allow us not to bear the burden of writing all the tests, forever.

The source package provides a test metadata file debian/tests/control. This is a file containing zero or more RFC822-style stanzas, along these lines:

        Tests: fred bill bongo
        Restrictions: needs-root breaks-computer

This means execute debian/tests/fred, debian/tests/bill, etc., each with no arguments, expecting exit status 0 and no stderr. The cwd is guaranteed to be the root of the source package which will have been built (but note that the tests must test the installed version). If the file to be executed has no execute bits set, chmod a+x is applied to it. TMPDIR will point to a directory for the execution of this particular test, which starts empty and will be deleted afterwards (so there is no need for the test to clean up files left there).

Restrictions:

If the stanza contains:

        Tests-Directory: path-from-source-root

then we execute path-from-source-root/fred, path-from-source-root/bar, etc. This allows tests to live outside the debian/ metadata area, so that they can more palatably be shared with non-Debian distributions.

Any unknown thing in Restrictions, or any unknown field in the RFC822 stanza, causes the tester core to skip the test with a message like `test environment does not support "blames-canada" restriction of test "simpsons"'.

Additional possibilities:

        Depends: ...
        Tests: filenamepattern*
        Restrictions: modifies-global-data needs-x-display

etc. - moves complexity from individual packages into central tester core.

A basic test could be simply running the binary and checking the result status (or other variants of this). Eventually every package would to be changed to include at least one test.

Ideally eventually where possible the upstream regression tests could be massaged so that they test the installed version. Whether this is possible and how best to achieve it has to be decided on a per-package basis.

Even integration tests can be represented like this: if one package's tests Depend on another package, then they are effectively integration tests. The actual tests can live in whichever package is most convenient.

Virtualisation interface

NOTE that this specification is no longer the master copy. The primary copy is in autopkgtest/doc/README.virtualisation-server. DO NOT EDIT this section in the wiki; it is retained here only for historical interest.

The virtualisation regime provides a single executable program which is used by the tester core to request virtualisation facilities.

The server has the following states:

(Note that these are the states of the server, in the tester core to server protocol. The actual testbed will probably have more states, including for example Closed, Open (and therefore busy), Modified, Broken, etc. Ideally the virtualisation regime will prevent multiple concurrent uses of the same testbed; the tester core is allowed to assume that either its caller or the virtualisation regime will ensure that it has exclusive use of the testbed.)

The server program is invoked with the argument --debian-package-testing and then proceeds to speak a protocol on its stdin/stdout. The protocol is line-based. In the future other ways of invoking the server may be defined; the current server should of course reject such invocations.

On any error including signals to the regime server or EOF on stdin the testbed is unreserved and restored to its original state (ie, closed), and the regime server will print a message to stderr (unless it is dying with a signal).

The representation of changes to the local filesystem is a directory containing zero or more of:

Invoking the test suites

The tester core will provide an interface which will be rich enough for build daemons or other automated test systems as well as interactive use by developers.

Integration of this functionality into Launchpad will be the next step - see Tasks for the Future, below.

The exact interface provided by the tester core to callers is not specified; the details will be as is convenient for the core to provide and will of course be properly documented.

For example, the interface might look something like this:

        $ debian/rules build
        $ sudo dchroot -d spong \
         dpkg -i ../name-of-binary-package_*.deb
        ...
        $ DEBIAN_TEST_VIRT=virt-chroot-boring-stupid \
         DEBIAN_TEST_VIRT_CHROOT=/dchroots/spong \
         debian-test-core-run-tests name-of-binary-package
        fred    PASS
        bill    SKIP needs-root
        bongo   FAIL see test-out-bongo.file.somewhere
        $ echo $?
        1
        $

or

        ...
        $ DEBIAN_TEST_VIRT=virt-chroot-boring-stupid \
         DEBIAN_TEST_VIRT_CHROOT=/dchroots/spong \
         debian-test-core-run-tests --deb name-of-binary-package_*.deb
        (install) PASS
        fred    PASS
        bill    SKIP needs-root
        bongo   FAIL see test-out-bongo.file.somewhere
        $ echo $?
        1
        $

Supported testing approaches, provided by the tester core to its caller, will include (or provide functionality sufficient for):

Other approaches which are convenient for developing tests, packages and testing software should be provided. The internal design, and/or external interface, of the tester core should make it easy to add approaches.

Rationale Q and A

Q. Why put the tests in the source package ?

A. Other possibilities include a special .deb generated by the source (which is a bit strange and what happens to this .deb and will make it even harder to reuse upstream test suites), or putting them in the .deb to be tested (definitely wrong - most people won't want the tests and they might be very large) or having them floating about separately somewhere (which prevents us from sharing and exchanging tests with other parts of the Free Software community). The source package is always available when development is taking place.

Q. Why the declarative test metadata, which has to be parsed, rather than just (say) a single test script to run ?

A. The script which was run would have to decide which tests to run, based (eg) on environment variables etc. It would end up replicating the machinery in the tester core, but this machinery would have to be in each package. This also makes it harder to report things like which individual tests were passed, failed, skipped, etc. The actual interface to the tester core would end up having to be nearly as complicated, anyway.

Q. Re execute program... virtualisation regime server command: ColinWatson: Many programs behave differently (relevantly so) depending on whether stdin/stdout/stderr are regular files, pipes, or terminals. Can we arrange to test these as well?

A. This is possible but we don't want to force the virtualisation regimes to directly support this. If necessary the test suite could provide its own wrapper scripts etc. to do this.

Q. ColinWatson: mdz and sabdfl would both like the per-package test metadata and the tests to be outside the debian/ directory, so that we can more conveniently share tests with non-Debian-based distributions in future. This does require inventing a name which won't be in use in any source packages.

A. The metadata should remain in debian/ because it contains data with format specified by, and meaning only relevant in the context of, Debian and derivatives. The tests can (in the latest spec) be elsewhere, using the new Tests-Directory stanza field.

Tasks for the future

Proposed tests

The minimum implementation profile to consider the goal achieved:

The remainder of this section lists suggestions for the implementer's initial set of tests. We expect the test suite to continuously expand and improve.

Check validity of binary packaging

Test installability:

  1. Start with a sandbox with only essential packages.
  2. Install all dependencies.
  3. Create a list of all files in the sandbox.
  4. Install the package.
  5. Run functional self tests of the package (see below).
  6. Reinstall the package to check that a (degraded) upgrading works.
  7. Remove the package.
  8. Remove all dependencies of the package.
  9. Purge the package. If this fails, then the purging code depends on non-essential packages, which is invalid.
  10. Create a list of all files in the sandbox and report any differences against the first list.

Test conflicts:

  1. Create a mapping installed file -> package from package contents lists.

  2. Create the union of all installed files.
  3. Remove all entries from that set whose file only appears once.
  4. Remove all pairs where the associated packages declare a conflict to each other.
  5. Ideally the remaining set should be empty, report all package names that are left.

(Note that apparently some Debian folks already do this, so there might be some scripts around).

Test debconf:

Test package contents:

Check validity of source package

Buildability is already tested on the buildd's. However, many packages have broken clean rules which leave the package in an unbuildable state. We should fix all packages where this is the case.

  1. Unpack the source package.
  2. dpkg-buildpackage

  3. Rename the resulting diff.gz to diff.gz-first

  4. dpkg-buildpackage; if this fails, the packaging is broken

  5. Compare the new diff.gz to diff.gz-first; if there is any difference, report this as a potentially broken package; however, many packages update config.{guess,sub}, so these should be excluded from the test

Package self tests

Build time self tests:

Run time self tests:

BOF braindump test suggestions


CategorySpec

AutomatedTesting (last edited 2008-08-06 16:16:33 by localhost)