diff --git a/test-templates/Makefile.am b/test-templates/Makefile.am new file mode 100644 index 0000000000..1238b787dc --- /dev/null +++ b/test-templates/Makefile.am @@ -0,0 +1,48 @@ +# A template Makefile.am for GLib g_test-based test directories. +# Copyright 2011 John Ralls + +include $(top_srcdir)/test-templates/Makefile.decl + + +#You will only need one of these: It points to the module directory +#after $(top_srcdir) or ${top_builddir}: +MODULEPATH = path/to/foo/ + +#The libtool convenience library to assemble the common test code +#(fixture code, setup and teardown routines, mocks, etc.). Use it only +#if there are a lot of test programs and support programs. For most +#cases it will make more sense to just include test_module_support.h +#and test_module_support.c in the test program sources & headers +#check_LTLIBRARIES = libgncmod_test_foo.la +# +#libgnc_test_foo_la_SOURCES = \ +# test_foo_support.c + +#The test program. You'll need to add to this if you have more than one module above. +TEST_PROGS += test-foo + +noinst_PROGRAMS = ${TEST_PROGS} + +#Program files for tests go here. It's probably best to have one for +#each file in the parent directory. Include +#test_foo_support.c if you have one and aren't building the +#support library. +test_foo_SOURCES = \ + test-foo.c \ + test-suite-module1.c \ + test-suite-module2.c \ + #etc. + +test_foo_HEADERSS = \ + $(top_srcdir)${MODULEPATH}module1.h \ + $(top_srcdir)${MODULEPATH}module2.h \ + #etc. + + +#The tests might require more libraries, but try to keep them +#as independent as possible. +test_foo_LDADD = ${top_buildir}${MODULEPATH}libgnc_foo.la + +test_foo_CFLAGS = \ + -I$(top_srcdir)${MODULEPATH} \ + ${GLIB_CFLAGS} diff --git a/test-templates/Makefile.decl b/test-templates/Makefile.decl new file mode 100644 index 0000000000..4d0f39bcc8 --- /dev/null +++ b/test-templates/Makefile.decl @@ -0,0 +1,62 @@ +# GLIB - Library of useful C routines + +GTESTER = gtester # for non-GLIB packages +GTESTER_REPORT = gtester_report # for non-GLIB packages +#GTESTER = $(top_builddir)/glib/gtester # for the GLIB package +#GTESTER_REPORT = $(top_builddir)/glib/gtester-report # for the GLIB package + +# initialize variables for unconditional += appending +EXTRA_DIST = +TEST_PROGS = + +### testing rules + +# test: run all tests in cwd and subdirs +test: ${TEST_PROGS} +if !PLATFORM_WIN32 + @test -z "${TEST_PROGS}" || ${GTESTER} --verbose ${TEST_PROGS} + @ for subdir in $(SUBDIRS) . ; do \ + test "$$subdir" = "." -o "$$subdir" = "po" || \ + ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \ + done +endif + +# test-report: run tests in subdirs and generate report +# perf-report: run tests in subdirs with -m perf and generate report +# full-report: like test-report: with -m perf and -m slow +test-report perf-report full-report: ${TEST_PROGS} + @test -z "${TEST_PROGS}" || { \ + case $@ in \ + test-report) test_options="-k";; \ + perf-report) test_options="-k -m=perf";; \ + full-report) test_options="-k -m=perf -m=slow";; \ + esac ; \ + if test -z "$$GTESTER_LOGDIR" ; then \ + ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \ + elif test -n "${TEST_PROGS}" ; then \ + ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \ + fi ; \ + } + @ ignore_logdir=true ; \ + if test -z "$$GTESTER_LOGDIR" ; then \ + GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \ + ignore_logdir=false ; \ + fi ; \ + for subdir in $(SUBDIRS) . ; do \ + test "$$subdir" = "." -o "$$subdir" = "po" || \ + ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \ + done ; \ + $$ignore_logdir || { \ + echo '' > $@.xml ; \ + echo '' >> $@.xml ; \ + for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \ + sed '1,1s/^?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \ + done ; \ + echo >> $@.xml ; \ + echo '' >> $@.xml ; \ + rm -rf "$$GTESTER_LOGDIR"/ ; \ + ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \ + } +.PHONY: test test-report perf-report full-report +# run make test as part of make check +check-local: test diff --git a/test-templates/README b/test-templates/README new file mode 100644 index 0000000000..df749f4902 --- /dev/null +++ b/test-templates/README @@ -0,0 +1,30 @@ +Unit Test Templates + +This directory contains three template files for setting up GLib +g_test operated unit tests in a test directory. If your module +directory doesn't already have one, create a test subdirectory and add +it to configure.ac. + +If there is already a test directory with make check tests in it, copy +the contents of the Makefile.am in this directory to the existing +Makefile.am; otherwise, copy the Makefile.am to your test directory. + +Copy test-module.c and test-suite.c to your test directory and rename +them appropriately. You will very likely want several copies of +test-suite.c, one corresponding to each c file in the module directory +that you're testing. + +Edit the test module file to call the (renamed) test_suite_module() in +each test-suite file. Add tests and fixtures as needed to the +test-suite files and add them to the (renamed) test_suite_module() +function. + +Edit Makefile.am according to the comments in the file. + +Run autogen.sh and configure. "make check" will run all tests; "make +test" will run only the GLib unit tests not guarded by conditionals +(see test-suite.c). + +See http://www.mail-archive.com/gtk-devel-list@gnome.org/msg06994.html +and http://library.gnome.org/devel/glib/stable/glib-Testing.html +for detailed documentation. diff --git a/test-templates/test-module.c b/test-templates/test-module.c new file mode 100644 index 0000000000..3baa59cdb2 --- /dev/null +++ b/test-templates/test-module.c @@ -0,0 +1,52 @@ +/******************************************************************** + * test_module.c: Example GLib g_test test execution file. * + * Copyright 2011 John Ralls * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * +\********************************************************************/ + + +#include + +/* Declare the test suite assembly functions (see test-suite.c) for + * each sub-suite; avoids having header files. */ +extern GTestSuite *test_suite_module1(); +extern GTestSuite *test_suite_module2(); +extern GTestSuite *test_suite_module3(); +extern GTestSuite *test_suite_module4(); + +int +main (int argc, + char *argv[]) +{ + g_type_init(); /* You may or may not need this, depending on + * whether the module you're testing or any + * dependencies use GObject. */ + g_test_init ( &argc, &argv ); /* initialize test program */ + qof_log_init_filename_special("/dev/null"); /* Initialize the + * gnucash logging system. Your tests will + * crash on the first logging call otherwise */ + test_suite_module1(); /* Call each suite assembly function */ + test_suite_module2(); + test_suite_module3(); + test_suite_module4(); + + return g_test_run(); /* Run the result */ +} + + diff --git a/test-templates/test-suite.c b/test-templates/test-suite.c new file mode 100644 index 0000000000..d9384c5952 --- /dev/null +++ b/test-templates/test-suite.c @@ -0,0 +1,113 @@ +/******************************************************************** + * test_submodule.c: Example GLib g_test test suite. * + * Copyright 2011 John Ralls * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * +\********************************************************************/ + +#include +#include +/* This is optional; you only need it if you have external fixtures or mocks. */ +#include "test_module_support.h" +/* Header for this module and any others that you need */ +#include + +/* Declare the test path for the suite. g_test_add_func automatically + * creates a nested set of test suites for us based on this path. */ +static const gchar *suitename = "module/module_1"; + +/* Test fixture: A struct, a setup function, and a teardown function are passed to g_test_add(); add getters, setters, and whatever other functions you need to call from your test functions. */ +typedef struct +{ + gint foo; + gdouble bar; +} Fixture; + +static void +setup_module_test(Fixture *fixture, gconstpointer pData) +{ +/* Do something useful */ +} + +static void +teardown_module_test(Fixture *fixture, gconstpointer pData) +{ +/* Clean up after ourselves */ +} + +static void +test_function( void ) +{ +/* A simple test function */ +} + +static void +test_function_with_data( gconstpointer data ) +{ +/* a more complicated function that needs arguments at invocation */ +} + +static void +test_function_with_fixture( Fixture *fixture, gconstpointer pData ) +{ +/* A really complicated function that needs an external test fixture */ +} + +static void +test_performance_function( void ) +{ +/* A slow function that measures performance of some critical + * routine. Note g_test_timer functions for simple perfomance + * measurements. */ +} + +/* Assert macros that you can use in your test functions. "cmp" is a + * comparison operator, one of ==, !=, <, >, <=, >=. + * + * g_assert( boolean_expression ) + * g_assert_not_reached() + * g_assert_cmpstr( gchar *s1, cmp, gchar *s2 ) + * g_assert_cmpint( int s1, cmp, int s2 ) + * g_assert_cmpuint( unsigned int s1, cmp, unsigned int s2 ) + * g_assert_cmphex( unsigned int s1, cmp, unsigned int s2 ) + * g_assert_cmpfloat( double s1, cmp, double s2 ) + * g_assert_no_error( GError *err ) + * g_assert_error( GError *err, GQuark domain, gint code ) + * + * You can also emit arbitrary messages into the test report with + * g_test_message( const char* format, ... ) + */ +GTestSuite* +test_suite_module1 ( void ) +{ + Datatype data = something(); + g_test_add_func( suitename, test_function ); + g_test_add_data_func( suitename, (gconstpointer)(&data), + test_function_with_data ); + g_test_add( suitename, Fixture, + data, + setup_module_test, + test_function_with_fixture, + teardown_module_test); +/* Other conditionals are g_test_quick(), g_test_slow(), and + * g_test_thorough() */ + if ( g_test_perf() ) + { + g_test_add_func( suitename, test_performance_func ); + } +} diff --git a/test-templates/testmain.c b/test-templates/testmain.c new file mode 100644 index 0000000000..c7d844ddb1 --- /dev/null +++ b/test-templates/testmain.c @@ -0,0 +1,46 @@ +/******************************************************************** + * testmain.c: GLib g_test test execution file. * + * Copyright 2011 John Ralls * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * +\********************************************************************/ + + +/* This is a template test program. Copy it to the test sudirectory and rename it test_modulename.c. (Use the same modulename that you gave Makefile.am in the same directory. +Write and link other test files */ +#include + +int +main (int argc, + char *argv[]) +{ + gtk_test_init (&argc, &argv); // initialize test program +/* Add test functions and suites. See + * http://library.gnome.org/devel/glib/stable/glib-Testing.html for + * details. Unfortunately, GLib-Testing doesn't provide the automatic + * registration features of more sophisitcated frameworks. */ + g_test_add_func ("/TESTPROG/Test Case Name", test_case_test_func); + ScannerFixture, // fixture structure type + NULL, // unused data argument + scanner_fixture_setup, // fixture setup + test_scanner_symbols, // test function + scanner_fixture_teardown); // fixture teardown + return g_test_run(); +} + +