Improve the test-templates README and update the templates to current practice.

This commit is contained in:
John Ralls
2015-07-28 11:45:22 -07:00
parent 124a2479ef
commit 2663dc96e2
4 changed files with 116 additions and 45 deletions

View File

@@ -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 the contents of the Makefile.am in this directory to the existing
Makefile.am; otherwise, copy the Makefile.am to your test directory. 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 There are two groups of templates here: testmain.c is for a standalone test
them appropriately. You will very likely want several copies of program that doesn't group tests into suites. test-module.c and test-suite.c
test-suite.c, one corresponding to each c file in the module directory support collecting a large number of tests separated in suites into a single
that you're testing. 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 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 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. function.
Edit Makefile.am according to the comments in the file. Edit Makefile.am according to the comments in the file.
Run autogen.sh and configure. "make check" will run all tests; "make Run autogen.sh and configure. "make check" will run all tests; "make test" will
test" will run only the GLib unit tests not guarded by conditionals run only the GLib unit tests not guarded by conditionals (see test-suite.c). For
(see test-suite.c). more control, use gtester as documented in the GLib docs.
See http://www.mail-archive.com/gtk-devel-list@gnome.org/msg06994.html See http://www.mail-archive.com/gtk-devel-list@gnome.org/msg06994.html
and http://library.gnome.org/devel/glib/stable/glib-Testing.html and http://library.gnome.org/devel/glib/stable/glib-Testing.html
for detailed documentation. for detailed documentation.
There are some helpful macros and message-trapping functions in
src/test-core/unittest-support.h.

View File

@@ -31,8 +31,7 @@ extern GTestSuite *test_suite_module3();
extern GTestSuite *test_suite_module4(); extern GTestSuite *test_suite_module4();
int int
main (int argc, main (int argc, char *argv[])
char *argv[])
{ {
qof_init(); /* You may or may not need this, depending on qof_init(); /* You may or may not need this, depending on
* whether the module you're testing or any * whether the module you're testing or any
@@ -48,5 +47,3 @@ main (int argc,
return g_test_run(); /* Run the result */ return g_test_run(); /* Run the result */
} }

View File

@@ -20,10 +20,13 @@
* Boston, MA 02110-1301, USA gnu@gnu.org * * 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 <config.h> #include <config.h>
#include <glib.h> #include <glib.h>
/* This is optional; you only need it if you have external fixtures or mocks. */ #include <unittest-support.h>
#include "test_module_support.h"
/* Header for this module and any others that you need */ /* Header for this module and any others that you need */
#include <module_1.h> #include <module_1.h>
@@ -31,7 +34,10 @@
* creates a nested set of test suites for us based on this path. */ * creates a nested set of test suites for us based on this path. */
static const gchar *suitename = "module/module_1"; 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 typedef struct
{ {
gint foo; gint foo;
@@ -39,15 +45,17 @@ typedef struct
} Fixture; } Fixture;
static void 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 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 static void
@@ -92,22 +100,23 @@ test_performance_function( void )
* You can also emit arbitrary messages into the test report with * You can also emit arbitrary messages into the test report with
* g_test_message( const char* format, ... ) * g_test_message( const char* format, ... )
*/ */
GTestSuite* void
test_suite_module1 ( void ) test_suite_module1 (void)
{ {
Datatype data = something(); Datatype data = something();
g_test_add_func( suitename, test_function ); GNC_TEST_ADD_FUNC (suitename, "Test Name 1", test_function);
g_test_add_data_func( suitename, (gconstpointer)(&data), {
test_function_with_data ); gchar *testpath = g_strdup_printf ("%s/Test Name 2", suitename);
g_test_add( suitename, Fixture, g_test_add_data_func( suitename, (gconstpointer)(&data),
data, test_function_with_data );
setup_module_test, g_free (testpath);
test_function_with_fixture, }
teardown_module_test); 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 /* Other conditionals are g_test_quick(), g_test_slow(), and
* g_test_thorough() */ * g_test_thorough() */
if ( g_test_perf() ) if ( g_test_perf() )
{ {
g_test_add_func( suitename, test_performance_func ); GNC_TEST_ADD_FUNC (suitename, "Test Name 4", test_performance_func);
} }
} }

View File

@@ -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 */ * This is a template test program. Copy it to the test sudirectory and rename
#include <glib/glib.h> * it test_modulename.c. (Use the same modulename that you gave Makefile.am in
* the same directory.
*/
#include <config.h>
#include <glib.h>
/* 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 int
main (int argc, main (int argc, char *argv[])
char *argv[])
{ {
gtk_test_init (&argc, &argv); // initialize test program qof_init(); /* You may or may not need this, depending on
/* Add test functions and suites. See * 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 * http://library.gnome.org/devel/glib/stable/glib-Testing.html for
* details. Unfortunately, GLib-Testing doesn't provide the automatic * details. Unfortunately, GLib-Testing doesn't provide the automatic
* registration features of more sophisitcated frameworks. */ * registration features of more sophisitcated frameworks. */
g_test_add_func ("/TESTPROG/Test Case Name", test_case_test_func); g_test_add_func ("/TESTPROG/Test Case Name 1", example_without_fixture);
ScannerFixture, // fixture structure type g_test_add_data_func ("/TESTPROG/Test Case Name 2", NULL);
NULL, // unused data argument g_test_add ("/TESTPROG/Test Case Name", Fixture, NULL, setup,
scanner_fixture_setup, // fixture setup example_with_fixture, teardown);
test_scanner_symbols, // test function
scanner_fixture_teardown); // fixture teardown
return g_test_run(); return g_test_run();
} }