Ver código fonte

test: make LolUnit's output match CppUnit's more closely.

legacy
Sam Hocevar sam 13 anos atrás
pai
commit
579f77bded
2 arquivos alterados com 111 adições e 39 exclusões
  1. +108
    -37
      src/lol/unit.h
  2. +3
    -2
      test/lol-test.cpp

+ 108
- 37
src/lol/unit.h Ver arquivo

@@ -17,6 +17,7 @@
#define __LOL_UNIT_H__

#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>

@@ -34,7 +35,7 @@ public:
virtual void tearDown(void) {};

protected:
FixtureBase() : m_next(NULL), m_tests(0), m_fails(0) {}
FixtureBase() : m_next(NULL), m_testcases(0), m_failcases(0) {}
virtual ~FixtureBase() {}

/* The FixtureBase class keeps track of all instanciated children
@@ -53,13 +54,16 @@ protected:
return head;
}

virtual int RunFixture() = 0;
virtual void RunFixture() = 0;

/* Prevent compiler complaints about unreachable code */
static inline bool True() { return true; }

FixtureBase *m_next;
int m_tests, m_fails;
int m_testcases, m_failcases;
int m_asserts, m_failure;
char const *m_fixturename, *m_currentname;
std::stringstream m_errorlog;
};

template<class T> class Fixture : protected FixtureBase
@@ -71,13 +75,13 @@ public:
{
public:
void (FixtureClass::* m_fun)();
char const *m_name;
char const *m_testname;
TestCase *m_next;

static void AddTestCase(TestCase *that, char const *name,
void (FixtureClass::*fun)())
{
that->m_name = name;
that->m_testname = name;
that->m_fun = fun;
GetOrSetTestCase(that);
}
@@ -89,14 +93,20 @@ public:
}

/* Run all test cases in this fixture. */
virtual int RunFixture()
virtual void RunFixture()
{
for (TestCase *head = GetOrSetTestCase(); head; head = head->m_next)
m_errorlog.str("");
m_testcases = 0;
m_failcases = 0;
for (TestCase *c = GetOrSetTestCase(); c; c = c->m_next)
{
(static_cast<FixtureClass *>(this)->*head->m_fun)();
std::cout << ".";
m_testcases++;
m_asserts = 0;
m_failure = false;
m_currentname = c->m_testname;
(static_cast<FixtureClass *>(this)->*c->m_fun)();
std::cout << (m_failure ? 'F' : '.');
}
return 0;
}

/* Each Fixture class specialisation keeps track of its instanciated
@@ -117,22 +127,53 @@ public:
class TestRunner
{
public:
int Run()
bool Run()
{
int ret = 0;
for (FixtureBase *head = FixtureBase::GetOrSetTest(); head; head = head->m_next)
bool ret = true;
std::stringstream errors("");
int failcases = 0, testcases = 0;

for (FixtureBase *f = FixtureBase::GetOrSetTest(); f; f = f->m_next)
{
head->setUp();
if (head->RunFixture())
ret = 1;
head->tearDown();
f->setUp();
f->RunFixture();
f->tearDown();

errors << f->m_errorlog.str();
testcases += f->m_testcases;
failcases += f->m_failcases;
}
std::cout << std::endl;

std::cout << std::endl << std::endl;
if (failcases)
{
std::cout << "!!!FAILURES!!!" << std::endl;
std::cout << "Test Results:" << std::endl;
std::cout << "Run: " << testcases
<< " Failures: " << failcases
<< " Errors: 0" << std::endl; /* TODO: handle errors */

std::cout << errors.str();
ret = false;
}
else
{
std::cout << "OK (" << testcases << " tests)" << std::endl;
}
std::cout << std::endl << std::endl;

return ret;
}
};

#define LOLUNIT_FIXTURE(FixtureName) \
class FixtureName; \
static char const *LolUnitFixtureName(FixtureName *p) \
{ \
(void)p; \
return #FixtureName; \
} \
class FixtureName : public lol::Fixture<FixtureName>

#define LOLUNIT_TEST(TestCaseName) \
@@ -145,36 +186,66 @@ public:
(void (FixtureClass::*)()) &FixtureClass::TestCaseName); \
} \
}; \
TestCase##TestCaseName test_case_##TestCaseName; \
TestCase##TestCaseName lol_unit_test_case_##TestCaseName; \
void TestCaseName()

#define LOLUNIT_SETUP_FIXTURE(ClassName) \
ClassName ClassName##Test_Instance;

#define LOLUNIT_ASSERT(cond) \
do { if (True() && !(cond)) \
{ \
std::cout << "FAIL! " #cond << std::endl; \
return; \
} } while(!True())
do { \
m_asserts++; \
if (True() && !(cond)) \
{ \
m_errorlog << std::endl << std::endl; \
m_errorlog << ++m_failcases << ") test: " \
<< LolUnitFixtureName(this) << "::" << m_currentname \
<< " (F) line: " << __LINE__ << " " \
<< __FILE__ << std::endl; \
m_errorlog << "assertion failed" << std::endl; \
m_errorlog << "- Expression: " << #cond << std::endl; \
m_failure = true; \
return; \
} \
} while(!True())

#define LOLUNIT_ASSERT_EQUAL(a, b) \
do { if (True() && (a) != (b)) \
{ \
std::cout << "FAIL! " #a " != " #b << std::endl; \
std::cout << "expected: " << (a) << std::endl; \
std::cout << "returned: " << (b) << std::endl; \
return; \
} } while(!True())
do { \
m_asserts++; \
if (True() && (a) != (b)) \
{ \
m_errorlog << std::endl << std::endl; \
m_errorlog << ++m_failcases << ") test: " \
<< LolUnitFixtureName(this) << "::" << m_currentname \
<< " (F) line: " << __LINE__ << " " \
<< __FILE__ << std::endl; \
m_errorlog << "equality assertion failed" << std::endl; \
m_errorlog << "- Expected: " << (b) << std::endl; \
m_errorlog << "- Actual : " << (a) << std::endl; \
m_errorlog << message; \
m_failure = true; \
return; \
} \
} while(!True())

#define LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, t) \
do { if (True() && fabs((a) - (b)) > fabs((t))) \
{ \
std::cout << "FAIL! " #a " != " #b << std::endl; \
std::cout << "expected: " << (a) << std::endl; \
std::cout << "returned: " << (b) << std::endl; \
return; \
} } while(!True())
do { \
m_asserts++; \
if (True() && fabs((a) - (b)) > fabs((t))) \
{ \
m_errorlog << std::endl << std::endl; \
m_errorlog << ++m_failcases << ") test: " \
<< LolUnitFixtureName(this) << "::" << m_currentname \
<< " (F) line: " << __LINE__ << " " \
<< __FILE__ << std::endl; \
m_errorlog << "double equality assertion failed" << std::endl; \
m_errorlog << "- Expected: " << (b) << std::endl; \
m_errorlog << "- Actual : " << (a) << std::endl; \
m_errorlog << "- Delta : " << (t) << std::endl; \
m_failure = true; \
return; \
} \
} while(!True())

} /* namespace lol */



+ 3
- 2
test/lol-test.cpp Ver arquivo

@@ -13,13 +13,14 @@
#endif

#include <cstdio>
#include <cstdlib>

#include <lol/unit.h>

int main(void)
{
lol::TestRunner runner;
int ret = !runner.Run();
return ret;
bool success = runner.Run();
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}


Carregando…
Cancelar
Salvar