| |
| Unit testing and guacamole-server |
| ================================= |
| |
| Unit tests within guacamole-server are implemented using the following: |
| |
| * automake, which allows arbitrary tests to be declared within `Makefile.am` |
| and uses `make check` to run those tests. |
| * CUnit (libcunit), a unit testing framework. |
| * `util/generate-test-runner.pl`, a Perl script which generates a test runner |
| written in C which leverages CUnit, running the unit tests declared in each |
| of the given `.c` files. The generated test runner produces output in [TAP |
| format](https://testanything.org/) which is consumed by the TAP test driver |
| provided by automake. |
| |
| Writing unit tests |
| ------------------ |
| |
| All unit tests should be within reasonably-isolated C source files, with each |
| logical test having its own function of the form: |
| |
| void test_SUITENAME__TESTNAME() { |
| ... |
| } |
| |
| where `TESTNAME` is the arbitrary name of the test and `SUITENAME` is the |
| arbitrary name of the test suite that this test belongs to. |
| |
| **This naming convention is required by `generate-test-runner.pl`.** Absolutely |
| all tests MUST follow the above convention if they are to be picked up and |
| organized by the test runner generation script. Functions which are not tests |
| MUST NOT follow the above convention so that they are _not_ picked up mistakenly |
| by the test runner generator as if they were tests. |
| |
| The `Makefile.am` for a subproject which contains such tests is typically |
| modified to contain a sections like the following: |
| |
| # |
| # Unit tests for myproj |
| # |
| |
| check_PROGRAMS = test_myproj |
| TESTS = $(check_PROGRAMS) |
| |
| test_myproj_SOURCES = \ |
| ...all source files... |
| |
| test_myproj_CFLAGS = \ |
| -Werror -Wall -pedantic \ |
| ...other flags... |
| |
| test_myproj_LDADD = \ |
| ...libraries... |
| |
| # |
| # Autogenerate test runner |
| # |
| |
| GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl |
| CLEANFILES = _generated_runner.c |
| |
| _generated_runner.c: $(test_myproj_SOURCES) |
| $(AM_V_GEN) $(GEN_RUNNER) $(test_myproj_SOURCES) > $@ |
| |
| nodist_test_libguac_SOURCES = \ |
| _generated_runner.c |
| |
| # Use automake's TAP test driver for running any tests |
| LOG_DRIVER = \ |
| env AM_TAP_AWK='$(AWK)' \ |
| $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh |
| |
| The above declares ... |
| |
| * ... that a binary, `test_myproj` should be built from the given sources. |
| Note that `test_myproj_SOURCES` contains only the source which was actually |
| written by hand while `nodist_test_myproj_SOURCES` contains only the source |
| which was generated by `generate-test-runner.pl`. |
| * ... that this `test_myproj` binary should be run to test this project when |
| `make check` is run, and that automake's TAP driver should be used to |
| consume its output. |
| * ... that the `_generated_runner.c` source file is generated dynamically |
| (through running `generate-test-runner.pl` on all non-generated test source) |
| and should not be distributed as part of the source archive. |
| |
| With tests following the above naming convention in place, and with the |
| necessary changes made to the applicable `Makefile.am`, all tests will be |
| run automatically when `make check` is run. |
| |