Pass/Fail coloring, Unit health, TestResult, TestLogger, UnitResult, UnitLogger.

This commit is contained in:
2024-08-15 16:40:17 -04:00
parent 42106670e5
commit 66ea6e4557
2 changed files with 167 additions and 11 deletions

View File

@@ -1,31 +1,90 @@
/// Josh Unit Test Library /// Josh Unit Test Library
#pragma once #pragma once
#include "iostream"
#include <functional> #include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
#include <source_location> #include <source_location>
#include <jlog/jlog.hpp> #include <jlog/jlog.hpp>
#include "jlog/io.hpp"
#include <Colors.hpp>
//#define NDEBUG for disabling assert, but tests still end up passing. //#define NDEBUG for disabling assert, but tests still end up passing.
// TODO: Move implementation to jtest::detail // TODO: Move implementation to jtest::detail
// have this file primarily expose the macros intended for users // have this file primarily expose the macros intended for users
namespace jtest { namespace jtest {
jlog::Logger JTestLog{"JTEST"}; class TestResult;
class TestLogger;
class Test;
class TestConnection;
class UnitResult;
class UnitLogger;
class Unit;
//TestLogger JTestLog;
//UnitLogger JUnitLog;
//jlog::Logger JTestLog{"JTEST"};
class TestResult : private jlog::LogEntry {
public:
TestResult(const std::string& name, bool passed, std::source_location location, jlog::Timestamp ts);
public:
std::string Name() { return this->name; };
bool Passed() { return passed; };
jlog::Timestamp GetTimeStamp() { return jlog::LogEntry::GetTimeStamp(); }
std::vector<jlog::token> Tokenize() override;
private:
//Test *test;
std::string name;
bool passed;
//jlog::Timestamp timestamp;
};
TestResult::TestResult(const std::string& name, bool passed, std::source_location location, jlog::Timestamp ts)
: jlog::LogEntry(passed ? Colors::Green : Colors::Red, name, passed ? "PASSED" : "FAILED", location, ts) {
IncludeTimestamp = true;
IncludeTrace = true;
//this->test = &t;
this->name = name;
this->passed = passed;
}
std::vector<jlog::token> TestResult::Tokenize() {
return jlog::LogEntry::Tokenize();
}
class TestLogger : private jlog::Logger {
public:
explicit TestLogger() : jlog::Logger("JTEST") {};
public:
void operator()(TestResult tr);
void Log(TestResult tr);
};
TestLogger JTestLog;
class Test { class Test {
public: public:
explicit Test(const std::string& name, std::function<void()> callback, std::source_location location = std::source_location::current()) { explicit Test(const std::string &name, std::function<void()> callback,
std::source_location location = std::source_location::current()) {
this->name = name; this->name = name;
this->callback = callback; this->callback = callback;
this->location = location; this->location = location;
}; };
public: public:
void operator () () { callback(); }; // <-- This will run our test and catch any exceptions. No it wont void operator()() { callback(); }; // <-- This will run our test and catch any exceptions. No it wont
std::string Name() { return name; }; std::string Name() { return name; };
std::source_location Location() { return location; }; std::source_location Location() { return location; };
protected: protected:
std::string name; std::string name;
@@ -34,10 +93,74 @@ namespace jtest {
}; };
void TestLogger::operator()(TestResult tr) {
return Log(tr);
}
void TestLogger::Log(jtest::TestResult tr) {
jlog::LogToConsole(tr.Tokenize());
jlog::LogToConsole("\n");
}
class UnitResult : private jlog::LogEntry {
public:
UnitResult(const std::string name, uint64_t testFailCount, uint64_t testPassCount, uint64_t testRunCount, uint64_t health, std::source_location location, jlog::Timestamp ts);
public:
std::string Name() { return name; };
uint64_t TestsFailed() { return testFailCount; };
uint64_t TestsPassed() { return testPassCount; };
float Health() { return health; }
//bool Passed() { return passed; };
jlog::Timestamp GetTimeStamp() { return jlog::LogEntry::GetTimeStamp(); }
std::vector<jlog::token> Tokenize() override;
private:
//Unit *unit;
std::string name;
uint64_t testFailCount;
uint64_t testPassCount;
uint64_t testRunCount;
float health;
//jlog::Timestamp timestamp;
};
// Yes this looks ugly as fuck
UnitResult::UnitResult(const std::string name, uint64_t testFailCount, uint64_t testPassCount, uint64_t testRunCount, uint64_t health, std::source_location location, jlog::Timestamp ts)
: jlog::LogEntry(Colors::Yellow, name, std::format("Passed: {}/{} Failed: {}/{} Health: {}%", testPassCount, testRunCount, testFailCount, testRunCount, health), location, ts)
{
//this->unit = &u;
this->name = name;
this->testPassCount = testPassCount;
this->testFailCount = testFailCount;
this->testRunCount = testRunCount;
this->health = health;
}
std::vector<jlog::token> UnitResult::Tokenize() {
return jlog::LogEntry::Tokenize();
}
class UnitLogger : private jlog::Logger {
public:
explicit UnitLogger() : jlog::Logger("JTEST") {};
public:
void operator()(UnitResult ur);
void Log(UnitResult ur);
};
void UnitLogger::operator()(UnitResult ur) {
return Log(ur);
}
void UnitLogger::Log(UnitResult ur) {
jlog::LogToConsole(ur.Tokenize());
jlog::LogToConsole("\n");
}
UnitLogger JUnitLog;
//class TestConnection; //class TestConnection;
class Unit;
class TestConnection { class TestConnection {
private: private:
@@ -63,16 +186,28 @@ namespace jtest {
using connection = TestConnection; using connection = TestConnection;
using test_ptr = std::shared_ptr<connection>; using test_ptr = std::shared_ptr<connection>;
public: public:
Unit(const std::string& name, std::source_location location = std::source_location::current()) {
this->name = name;
this->location = location;
};
std::string Name() { return name; };
std::source_location Location() { return location; };
uint64_t TestCount() { return testCounter; };
void Invoke(); void Invoke();
void operator()(); void operator()();
connection Connect(delegate callback); connection Connect(delegate callback);
connection operator+=(delegate callback); connection operator+=(delegate callback);
private: private:
std::string name;
std::source_location location;
std::vector<test_ptr> tests; std::vector<test_ptr> tests;
uint64_t testCounter = 0; uint64_t testCounter = 0;
}; };
void Unit::Invoke() { void Unit::Invoke() {
uint64_t passCounter = 0;
uint64_t failCounter = 0;
uint64_t runCounter = 0;
for (test_ptr &connection_ptr: this->tests) { for (test_ptr &connection_ptr: this->tests) {
//connection_ptr->Invoke(); //connection_ptr->Invoke();
@@ -83,12 +218,28 @@ namespace jtest {
catch(...) // <- Basically covers all exception cases. GTest does something similar catch(...) // <- Basically covers all exception cases. GTest does something similar
{ passed = false; } { passed = false; }
Test d = connection_ptr->GetDelegate(); runCounter++;
if(!passed) Test t = connection_ptr->GetDelegate();
JTestLog(std::format("{} - FAILED", d.Name()), d.Location()); TestResult r{std::format("{}::{}", name, t.Name()), passed, t.Location(), jlog::Timestamp()};
else
JTestLog(std::format("{} - PASSED", d.Name()), d.Location()); if(!passed) {
failCounter++;
//JTestLog(std::format(
// "{} - FAILED - [{}/{}]",
// d.Name(), runCounter, testCounter), d.Location());
} else {
passCounter++;
//JTestLog(std::format("{} - FAILED",d.Name(),d.Location()));//, runCounter, testCounter));
//JTestLog(std::format(
// "{} - PASSED - [{}/{}]",
// d.Name(), runCounter, testCounter), d.Location());
}
JTestLog(r);
} }
uint64_t health = float(passCounter)/float(runCounter)*100;
std::cout << std::to_string(health) << std::endl;
UnitResult ur{name, failCounter, passCounter, runCounter, health, location, jlog::Timestamp()};
JUnitLog(ur);
} }
void Unit::operator()() { Invoke();} void Unit::operator()() { Invoke();}
@@ -96,7 +247,7 @@ namespace jtest {
TestConnection Unit::Connect(delegate callback) TestConnection Unit::Connect(delegate callback)
{ {
test_ptr retval(new connection(this, callback)); test_ptr retval(new connection(this, callback));
this->tests.push_back(retval); this->tests.push_back(retval); testCounter++;
return *retval; return *retval;
} }
@@ -116,6 +267,11 @@ namespace jtest {
/* /*
class Unit { class Unit {

View File

@@ -19,7 +19,7 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
jtest::Unit ThisDick; jtest::Unit ThisDick{"This Dick"};
ThisDick += jtest::Test("bawls", []{ printf("FUCK1\n"); }); ThisDick += jtest::Test("bawls", []{ printf("FUCK1\n"); });