Added SetUp/TearDown functions for test suites.
authorMarkus Kauppila <markus.kauppila@gmail.com>
Mon, 11 Jul 2011 17:55:35 +0300
changeset 5754 2eead798346a
parent 5753 5e8c5282cac0
child 5755 35d4ae5dea90
Added SetUp/TearDown functions for test suites.
test/test-automation/SDL_test.c
test/test-automation/SDL_test.h
test/test-automation/runner.c
test/test-automation/testdummy/testdummy.c
--- a/test/test-automation/SDL_test.c	Mon Jul 11 17:47:55 2011 +0300
+++ b/test/test-automation/SDL_test.c	Mon Jul 11 17:55:35 2011 +0300
@@ -1,4 +1,4 @@
-/*
+	/*
   Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com>
 
   This software is provided 'as-is', without any express or implied
@@ -36,7 +36,7 @@
 int _testAssertsPassed;
 
 void
-_TestCaseInit()
+_InitTestEnvironment() // InitTestEnvironment
 {
 	_testReturnValue = 0;
 	_testAssertsFailed = 0;
@@ -44,7 +44,7 @@
 }
 
 int
-_TestCaseQuit()
+_QuitTestEnvironment()
 {
 	AssertSummary(_testAssertsFailed + _testAssertsPassed,
                   _testAssertsFailed, _testAssertsPassed, time(0));
@@ -76,7 +76,6 @@
 	   AssertWithValues("AssertEquals", 1, buf,
     		  actual, expected, time(0));
 
-      _testReturnValue = 0;
       _testAssertsPassed++;
    }
 }
@@ -98,7 +97,6 @@
    } else {
 		Assert("AssertTrue", 1, buf, time(0));
 
-		_testReturnValue = 0;
 		_testAssertsPassed++;
    }
 }
@@ -115,7 +113,6 @@
 
    Assert("AssertPass", 1, buf, time(0));
 
-   _testReturnValue = 0;
    _testAssertsPassed++;
 }
 
--- a/test/test-automation/SDL_test.h	Mon Jul 11 17:47:55 2011 +0300
+++ b/test/test-automation/SDL_test.h	Mon Jul 11 17:55:35 2011 +0300
@@ -25,6 +25,10 @@
 
 #include "logger.h"
 
+#include "common/common.h"
+#include "common/images.h"
+
+
 extern int _testReturnValue;
 extern int _testAssertsFailed;
 extern int _testAssertsPassed;
@@ -52,18 +56,18 @@
 } TestCaseReference;
 
 /*!
- *  Initialized the test case. Must be called at
- *  the beginning of every test case, before doing
- *  anything else.
+ *  Initialized the test environment such as asserts. Must be called at
+ *  the beginning of every test case, before doing anything else.
  */
-void _TestCaseInit();
+void _InitTestEnvironment();
 
 /*!
- *  Deinitializes and exits the test case
+ *  Deinitializes the test environment and
+ *  returns the result of the test (pass or failure)
  *
  * \return 0 if test succeeded, otherwise 1
  */
-int _TestCaseQuit();
+int _QuitTestEnvironment();
 
 /*!
  *  Assert function. Tests if the expected value equals the actual value, then
@@ -74,6 +78,7 @@
  * \param message Message that will be printed if assert fails
  */
 void AssertEquals(const int expected, const int actual, char *message, ...);
+
 /*!
  *  Assert function. Tests if the given condition is true. True in
  *  this case means non-zero value. If the condition is true, the
--- a/test/test-automation/runner.c	Mon Jul 11 17:47:55 2011 +0300
+++ b/test/test-automation/runner.c	Mon Jul 11 17:55:35 2011 +0300
@@ -39,9 +39,13 @@
 //!< Function pointer to a test case function
 typedef void (*TestCaseFp)(void *arg);
 //!< Function pointer to a test case init function
-typedef void (*TestCaseInitFp)(void);
+typedef void (*InitTestInvironmentFp)(void);
 //!< Function pointer to a test case quit function
-typedef int  (*TestCaseQuitFp)(void);
+typedef int  (*QuitTestInvironmentFp)(void);
+//!< Function pointer to a test case set up function
+typedef void (*TestCaseSetUpFp)(void *arg);
+//!< Function pointer to a test case tear down function
+typedef void  (*TestCaseTearDownFp)(void *arg);
 
 
 //!< Flag for executing tests in-process
@@ -105,20 +109,24 @@
 	long requirements;
 	long timeout;
 
-	TestCaseInitFp testCaseInit;
+	InitTestInvironmentFp initTestEnvironment;
+	TestCaseSetUpFp testSetUp;
 	TestCaseFp testCase;
-	TestCaseQuitFp testCaseQuit;
+	TestCaseTearDownFp testTearDown;
+ 	QuitTestInvironmentFp quitTestEnvironment;
 
 	struct TestCaseItem *next;
 } TestCase;
 
 
-
 /*! Some function prototypes. Add the rest of functions and move to runner.h */
 TestCaseFp LoadTestCaseFunction(void *suite, char *testName);
-TestCaseInitFp LoadTestCaseInitFunction(void *suite);
-TestCaseQuitFp LoadTestCaseQuitFunction(void *suite);
+InitTestInvironmentFp LoadInitTestInvironmentFunction(void *suite);
+QuitTestInvironmentFp LoadQuitTestInvironmentFunction(void *suite);
 TestCaseReference **QueryTestCaseReferences(void *library);
+TestCaseSetUpFp LoadTestSetUpFunction(void *suite);
+TestCaseTearDownFp LoadTestTearDownFunction(void *suite);
+
 
 /*! Pointers to selected logger implementation */
 RunStartedFp RunStarted = NULL;
@@ -159,18 +167,26 @@
 			void *suite = suiteReference->library;
 
 			// Load test case functions
-			TestCaseInitFp testCaseInit = LoadTestCaseInitFunction(suiteReference->library);
-			TestCaseQuitFp testCaseQuit = LoadTestCaseQuitFunction(suiteReference->library);
-			TestCaseFp testCase = (TestCaseFp) LoadTestCaseFunction(suiteReference->library, testReference->name);
+			InitTestInvironmentFp initTestEnvironment = LoadInitTestInvironmentFunction(suiteReference->library);
+			QuitTestInvironmentFp quitTestEnvironment = LoadQuitTestInvironmentFunction(suiteReference->library);
+
+			TestCaseSetUpFp testSetUp = LoadTestSetUpFunction(suiteReference->library);
+			TestCaseTearDownFp testTearDown = LoadTestTearDownFunction(suiteReference->library);
+
+			TestCaseFp testCase = LoadTestCaseFunction(suiteReference->library, testReference->name);
 
 			// Do the filtering
 			if(FilterTestCase(testReference)) {
 				TestCase *item = SDL_malloc(sizeof(TestCase));
 				memset(item, 0, sizeof(TestCase));
 
-				item->testCaseInit = testCaseInit;
+				item->initTestEnvironment = initTestEnvironment;
+				item->quitTestEnvironment = quitTestEnvironment;
+
+				item->testSetUp = testSetUp;
+				item->testTearDown = testTearDown;
+
 				item->testCase = testCase;
-				item->testCaseQuit = testCaseQuit;
 
 				// copy suite name
 				int length = SDL_strlen(suiteReference->name) + 1;
@@ -287,7 +303,9 @@
 
 	Entry *entry = NULL;
 	if(!directory) {
-		perror("Couldn't open test suite directory!");
+		fprintf(stderr, "Failed to open test suite directory: %s\n", directoryName);
+		perror("Error message");
+		exit(1);
 	}
 
 	while(entry = readdir(directory)) {
@@ -458,42 +476,82 @@
 
 
 /*!
- * Loads function that initialises the test case from the
- * given test suite.
+ * Loads function that sets up a fixture for a test case. Note: if there's
+ * no SetUp function present in the suite the function will return NULL.
  *
  * \param suite Used test suite
  *
- * \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails.
+ * \return Function pointer to test case's set up function
  */
-TestCaseInitFp
-LoadTestCaseInitFunction(void *suite) {
-	TestCaseInitFp testCaseInit = (TestCaseInitFp) SDL_LoadFunction(suite, "_TestCaseInit");
-	if(testCaseInit == NULL) {
-		fprintf(stderr, "Loading TestCaseInit function failed, testCaseInit == NULL\n");
+TestCaseSetUpFp
+LoadTestSetUpFunction(void *suite) {
+	TestCaseSetUpFp testSetUp = (TestCaseSetUpFp) SDL_LoadFunction(suite, "SetUp");
+	if(testSetUp == NULL) {
+		fprintf(stderr, "Loading SetUp function failed, testSetUp == NULL\n");
 		fprintf(stderr, "%s\n", SDL_GetError());
 	}
 
-	return testCaseInit;
+	return testSetUp;
 }
 
 
 /*!
- * Loads function that deinitialises the executed test case from the
- * given test suite.
+ * Loads function that tears down a fixture for a test case. Note: if there's
+ * no TearDown function present in the suite the function will return NULL.
+ *
+ * \param suite Used test suite
+ *
+ * \return Function pointer to test case's tear down function
+ */
+TestCaseTearDownFp
+LoadTestTearDownFunction(void *suite) {
+	TestCaseTearDownFp testTearDown = (TestCaseTearDownFp) SDL_LoadFunction(suite, "TearDown");
+	if(testTearDown == NULL) {
+		fprintf(stderr, "Loading TearDown function failed, testTearDown == NULL\n");
+		fprintf(stderr, "%s\n", SDL_GetError());
+	}
+
+	return testTearDown;
+}
+
+
+/*!
+ * Loads function that initialises the test environment for
+ * a test case in the given suite.
  *
  * \param suite Used test suite
  *
- * \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails.
+ * \return Function pointer (InitTestInvironmentFp) which points to loaded init function. NULL if function fails.
  */
-TestCaseQuitFp
-LoadTestCaseQuitFunction(void *suite) {
-	TestCaseQuitFp testCaseQuit = (TestCaseQuitFp) SDL_LoadFunction(suite, "_TestCaseQuit");
-	if(testCaseQuit == NULL) {
-		fprintf(stderr, "Loading TestCaseQuit function failed, testCaseQuit == NULL\n");
+InitTestInvironmentFp
+LoadInitTestInvironmentFunction(void *suite) {
+	InitTestInvironmentFp testEnvInit = (InitTestInvironmentFp) SDL_LoadFunction(suite, "_InitTestEnvironment");
+	if(testEnvInit == NULL) {
+		fprintf(stderr, "Loading _InitTestInvironment function failed, testEnvInit == NULL\n");
 		fprintf(stderr, "%s\n", SDL_GetError());
 	}
 
-	return testCaseQuit;
+	return testEnvInit;
+}
+
+
+/*!
+ * Loads function that deinitialises the test environment (and returns
+ * the test case's result) created for the test case in the given suite.
+ *
+ * \param suite Used test suite
+ *
+ * \return Function pointer (QuitTestInvironmentFp) which points to loaded init function. NULL if function fails.
+ */
+QuitTestInvironmentFp
+LoadQuitTestInvironmentFunction(void *suite) {
+	QuitTestInvironmentFp testEnvQuit = (QuitTestInvironmentFp) SDL_LoadFunction(suite, "_QuitTestEnvironment");
+	if(testEnvQuit == NULL) {
+		fprintf(stderr, "Loading _QuitTestEnvironment function failed, testEnvQuit == NULL\n");
+		fprintf(stderr, "%s\n", SDL_GetError());
+	}
+
+	return testEnvQuit;
 }
 
 
@@ -536,19 +594,37 @@
 ExecuteTest(TestCase *testItem) {
 	int retVal = 1;
 	if(execute_inproc) {
-		testItem->testCaseInit();
+		testItem->initTestEnvironment();
+
+		if(testItem->testSetUp) {
+			testItem->testSetUp(0x0);
+		}
 
 		testItem->testCase(0x0);
 
-		retVal = testItem->testCaseQuit();
+		if(testItem->testTearDown) {
+			testItem->testTearDown(0x0);
+		}
+
+		retVal = testItem->quitTestEnvironment();
 	} else {
 		int childpid = fork();
 		if(childpid == 0) {
-			testItem->testCaseInit();
+			testItem->initTestEnvironment();
+
+			if(testItem->testSetUp) {
+				testItem->testSetUp(0x0);
+			}
 
 			testItem->testCase(0x0);
 
-			exit(testItem->testCaseQuit());
+			// note: if test case is is aborted by some signal
+			// then TearDown function won't be called
+			if(testItem->testTearDown) {
+				testItem->testTearDown(0x0);
+			}
+
+			exit(testItem->quitTestEnvironment());
 		} else {
 			int stat_lock = -1;
 			int child = wait(&stat_lock);
--- a/test/test-automation/testdummy/testdummy.c	Mon Jul 11 17:47:55 2011 +0300
+++ b/test/test-automation/testdummy/testdummy.c	Mon Jul 11 17:55:35 2011 +0300
@@ -21,7 +21,7 @@
 /*! \file
  * Dummy test suite for test runner. This can be used as a base for
  * writing new tests. Dummy suite also works as reference to using
- * various asserts and (possible) other utilities.
+ * various asserts and other (possible) utilities.
  */
 
 #include <stdio.h>
@@ -30,8 +30,6 @@
 
 #include "../SDL_test.h"
 
-// \todo add some helpful commenting for possible test writers?
-
 /* Test case references */
 static const TestCaseReference test1 =
 		(TestCaseReference){ "dummycase1", "description", TEST_ENABLED, 0, 0};
@@ -52,6 +50,37 @@
 	return (TestCaseReference **)testSuite;
 }
 
+/* Create test fixture */
+
+/*!
+ * SetUp function can be used to create a test fixture for test cases.
+ * The function will be called right before executing the test case.
+ *
+ * Note: this function is optional.
+ *
+ * \param arg parameters given to test. Usually NULL
+ */
+void
+SetUp(void *arg)
+{
+	// create test fixture,
+	// for example, set up static variables used by test cases here
+}
+
+/*!
+ * TearDown function can be used to destroy a test fixture for test cases.
+ * The function will be called right after executing the test case.
+ *
+ * Note: this function is optional.
+ *
+ * \param arg parameters given to test. Usually NULL
+ */
+void
+TearDown(void *arg)
+{
+	// destroy test fixture
+}
+
 /* Test case functions */
 void
 dummycase1(void *arg)