diff --git a/test-templates/README b/test-templates/README index df749f49029..0a5a026dc30 100644 --- a/test-templates/README +++ b/test-templates/README @@ -9,22 +9,35 @@ 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. +There are two groups of templates here: testmain.c is for a standalone test +program that doesn't group tests into suites. test-module.c and test-suite.c +support collecting a large number of tests separated in suites into a single +test program. In most cases you'll want to use the latter. + +For a single file test program, copy testmain.c into your test directory, +renaming it appropriately. Write fixtures and test functions as needed and +register them in main(). Create a target in Makefile.am which has this file as +its source. + +To use suites, 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() +test-suite files and register them in 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). +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). For +more control, use gtester as documented in the GLib docs. 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. + +There are some helpful macros and message-trapping functions in +src/test-core/unittest-support.h. diff --git a/test-templates/test-module.c b/test-templates/test-module.c index 5e1fdf213ad..86861987743 100644 --- a/test-templates/test-module.c +++ b/test-templates/test-module.c @@ -31,8 +31,7 @@ extern GTestSuite *test_suite_module3(); extern GTestSuite *test_suite_module4(); int -main (int argc, - char *argv[]) +main (int argc, char *argv[]) { qof_init(); /* You may or may not need this, depending on * whether the module you're testing or any @@ -48,5 +47,3 @@ main (int argc, return g_test_run(); /* Run the result */ } - - diff --git a/test-templates/test-suite.c b/test-templates/test-suite.c index 181a534644a..a8f1832487b 100644 --- a/test-templates/test-suite.c +++ b/test-templates/test-suite.c @@ -20,10 +20,13 @@ * Boston, MA 02110-1301, USA gnu@gnu.org * \********************************************************************/ +/* This is a template test suite. Copy it to the test directory and name it for + * the corresponding file you're testing with a "utest-" prefix. Add it to the + * test_program_SOURCES in Makefile.am. + */ #include #include -/* This is optional; you only need it if you have external fixtures or mocks. */ -#include "test_module_support.h" +#include /* Header for this module and any others that you need */ #include @@ -31,7 +34,10 @@ * 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. */ +/* 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; @@ -39,15 +45,17 @@ typedef struct } Fixture; static void -setup_module_test(Fixture *fixture, gconstpointer pData) +setup (Fixture *fixture, gconstpointer pData) { - /* Do something useful */ + /* Whatever is needed to populate the fixture and initialize your module for + * running a single test. + */ } static void -teardown_module_test(Fixture *fixture, gconstpointer pData) +teardown (Fixture *fixture, gconstpointer pData) { - /* Clean up after ourselves */ + /* Whatever cleanup is needed at the end of the test. */ } static void @@ -92,22 +100,23 @@ test_performance_function( void ) * You can also emit arbitrary messages into the test report with * g_test_message( const char* format, ... ) */ -GTestSuite* -test_suite_module1 ( void ) +void +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); + GNC_TEST_ADD_FUNC (suitename, "Test Name 1", test_function); + { + gchar *testpath = g_strdup_printf ("%s/Test Name 2", suitename); + g_test_add_data_func( suitename, (gconstpointer)(&data), + test_function_with_data ); + g_free (testpath); + } + GNC_TEST_ADD (suitename, "Test Name 3", Fixture, data, setup, + test_function_with_fixture, teardown); /* 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 ); + GNC_TEST_ADD_FUNC (suitename, "Test Name 4", test_performance_func); } } diff --git a/test-templates/testmain.c b/test-templates/testmain.c index a1c2908d628..ba53fb938d5 100644 --- a/test-templates/testmain.c +++ b/test-templates/testmain.c @@ -21,26 +21,78 @@ \********************************************************************/ -/* 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 +/** + * 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. + */ +#include +#include +/* Add any headers you need for the functions you're testing. */ + +/* 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 +{ + int a; + char* b; +} Fixture; + +static void +setup (Fixture *fixture, gconstpointer pData) +{ + /* Whatever is needed to populate the fixture and initialize your module for + * running a single test. + */ +} + +static void +teardown (Fixture *fixture, gconstpointer pData) +{ + /* Whatever cleanup is needed at the end of the test. */ +} + +static void +example_without_fixture (void) +{ + /* This test doesn't need the fixture or any preconditions. You might use + * this for a constructor test, for example. + */ +} + +static void +example_with_data( gconstpointer data ) +{ + /* We want to be able to call this function more than once with different + * data. + */ +} + +static void +example_with_fixture (Fixture *fixture, gconstpointer pData) +{ + /* This one uses the fixture. */ +} int -main (int argc, - char *argv[]) +main (int argc, char *argv[]) { - gtk_test_init (&argc, &argv); // initialize test program - /* Add test functions and suites. See + qof_init(); /* You may or may not need this, depending on + * whether the module you're testing or any + * dependencies use GObject. */ + qof_log_init_filename_special("/dev/null"); /* Initialize the + * gnucash logging system. Your tests will + * crash on the first logging call otherwise */ + g_test_init (&argc, &argv, NULL); // initialize test program + /* Add test functions. 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 + g_test_add_func ("/TESTPROG/Test Case Name 1", example_without_fixture); + g_test_add_data_func ("/TESTPROG/Test Case Name 2", NULL); + g_test_add ("/TESTPROG/Test Case Name", Fixture, NULL, setup, + example_with_fixture, teardown); return g_test_run(); } - -