slogan3

Help me bij het maken van een aangepaste C++-raamwerk voor unittests

description

Door een aangepast unittest-ramenwerk te ontwikkelen, kan ik ervoor zorgen dat mijn C++-code grondig wordt getest, een hoge codekwaliteit behouden en problemen snel identificeren tijdens de ontwikkeling.

prompt

try_prompt

Help me bij het ontwerpen en implementeren van een aangepast raamwerk voor unittests in C++. Ik wil functies opnemen zoals testgevalbeheer, assertiebehandeling en rapport ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder geef ik een basisstructuur voor een zelfgemaakt unittest-raamwerk in C++, gericht op assertions en testrapportage. Dit voorbeeld bevat: - Een eenvoudige manier om tests te definiëren en uit te voeren - Assertiemethoden - Rapportage van testresultaten --- **1. Basisstructuur van het raamwerk** ```cpp #include <iostream> #include <vector> #include <string> struct TestResult { std::string testnaam; bool geslaagd; std::string foutmelding; }; class TestSuite { private: std::vector<TestResult> resultaten; public: void voegTestToe(const std::string& naam, void(*testfunctie)()) { // Voer de test uit en registreer resultaat try { testfunctie(); resultaten.push_back({naam, true, ""}); } catch (const std::string& fout) { resultaten.push_back({naam, false, fout}); } catch (...) { resultaten.push_back({naam, false, "Onbekende fout"}); } } void rapportage() const { int geslaagdCount = 0; for (const auto& res : resultaten) { if (res.geslaagd) { std::cout << "[PASSED] " << res.testnaam << std::endl; geslaagdCount++; } else { std::cout << "[FAILED] " << res.testnaam << " - Fout: " << res.foutmelding << std::endl; } } std::cout << "\nTotaal tests: " << resultaten.size() << ", Geslaagd: " << geslaagdCount << ", Gefaald: " << resultaten.size() - geslaagdCount << std::endl; } }; ``` --- **2. Assertiemethoden** ```cpp void assertEquals(int verwachte, int werkelijke, const std::string& message = "") { if (verwachte != werkelijke) { throw "assertEquals gefaald: " + message + " (verwacht " + std::to_string(verwachte) + ", gevonden " + std::to_string(werkelijke) + ")"; } } void assertTrue(bool conditie, const std::string& message = "") { if (!conditie) { throw "assertTrue gefaald: " + message; } } ``` --- **3. Voorbeeld testgevallen** ```cpp void testOptellen() { int resultaat = 2 + 2; assertEquals(4, resultaat, "Optellen test"); } void testBoolean() { bool waarde = (5 > 3); assertTrue(waarde, "Vergelijking 5 > 3"); } ``` --- **4. Main functie om tests uit te voeren** ```cpp int main() { TestSuite suite; suite.voegTestToe("Test Optellen", &testOptellen); suite.voegTestToe("Test Boolean", &testBoolean); suite.rapportage(); return 0; } ``` --- **Samenvatting:** - Definieer een `TestSuite` voor het beheren van testcases en rapportage. - Gebruik functies zoals `assertEquals` en `assertTrue` voor assertions. - Voeg tests toe met `voegTestToe` en voer de rapportage uit. Wil je meer functies toevoegen, zoals setup/teardown, parameterized tests, of meer uitgebreide rapportages?
provider: deepseek
model: deepseek-chat
Zeker! Ik help je bij het ontwerpen van een eenvoudig maar krachtig unittestraamwerk in C++. Hier is een complete implementatie met de gevraagde functies: ## Basisstructuur van het raamwerk ```cpp // test_framework.h #include <iostream> #include <string> #include <vector> #include <sstream> class TestCase { private: std::string name; bool passed; std::string failure_message; public: TestCase(const std::string& test_name) : name(test_name), passed(true) {} virtual void run() = 0; const std::string& getName() const { return name; } bool isPassed() const { return passed; } const std::string& getFailureMessage() const { return failure_message; } protected: void assertTrue(bool condition, const std::string& message = "") { if (!condition) { passed = false; failure_message = message.empty() ? "Assertion failed: expected true" : message; } } void assertFalse(bool condition, const std::string& message = "") { assertTrue(!condition, message.empty() ? "Assertion failed: expected false" : message); } template<typename T> void assertEquals(const T& expected, const T& actual, const std::string& message = "") { if (expected != actual) { passed = false; std::ostringstream oss; oss << (message.empty() ? "Assertion failed" : message) << ": expected '" << expected << "', got '" << actual << "'"; failure_message = oss.str(); } } void assertThrows(void (*function)(), const std::string& expected_exception = "") { try { function(); passed = false; failure_message = "Expected exception was not thrown"; } catch (const std::exception& e) { if (!expected_exception.empty() && expected_exception != typeid(e).name()) { passed = false; failure_message = "Wrong exception type thrown"; } } catch (...) { if (!expected_exception.empty()) { passed = false; failure_message = "Wrong exception type thrown"; } } } }; class TestSuite { private: std::string suite_name; std::vector<TestCase*> test_cases; public: TestSuite(const std::string& name) : suite_name(name) {} void addTestCase(TestCase* test_case) { test_cases.push_back(test_case); } void runAll() { std::cout << "Uitvoeren testsuite: " << suite_name << std::endl; std::cout << "=========================================" << std::endl; int passed_count = 0; int total_count = test_cases.size(); for (auto test_case : test_cases) { test_case->run(); if (test_case->isPassed()) { std::cout << "✓ PASS: " << test_case->getName() << std::endl; passed_count++; } else { std::cout << "✗ FAIL: " << test_case->getName() << std::endl; std::cout << " Reden: " << test_case->getFailureMessage() << std::endl; } } std::cout << "=========================================" << std::endl; std::cout << "Resultaat: " << passed_count << "/" << total_count << " geslaagd" << std::endl; std::cout << std::endl; } ~TestSuite() { for (auto test_case : test_cases) { delete test_case; } } }; // Macro's voor gemakkelijke testdefinitie #define TEST_CASE(test_name) \ class test_name##_Test : public TestCase { \ public: \ test_name##_Test() : TestCase(#test_name) {} \ void run() override; \ }; \ void test_name##_Test::run() #define ADD_TEST(suite, test_name) \ suite.addTestCase(new test_name##_Test()) ``` ## Voorbeeldgebruik ```cpp // example_tests.cpp #include "test_framework.h" #include <cmath> // Eenvoudige wiskundige functies om te testen int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } double divide(double a, double b) { if (b == 0) throw std::invalid_argument("Deling door nul"); return a / b; } // Testgevallen TEST_CASE(TestAddition) { assertEquals(5, add(2, 3), "2 + 3 moet 5 zijn"); assertEquals(0, add(-1, 1), "-1 + 1 moet 0 zijn"); assertEquals(-5, add(-2, -3), "-2 + -3 moet -5 zijn"); } TEST_CASE(TestMultiplication) { assertEquals(6, multiply(2, 3), "2 * 3 moet 6 zijn"); assertEquals(0, multiply(5, 0), "5 * 0 moet 0 zijn"); assertEquals(-6, multiply(2, -3), "2 * -3 moet -6 zijn"); } TEST_CASE(TestDivision) { assertEquals(2.0, divide(6.0, 3.0), "6.0 / 3.0 moet 2.0 zijn"); assertEquals(0.5, divide(1.0, 2.0), "1.0 / 2.0 moet 0.5 zijn"); // Test op uitzondering assertThrows([]() { divide(5.0, 0.0); }, "Deling door nul moet uitzondering gooien"); } TEST_CASE(TestBooleanAssertions) { assertTrue(5 > 3, "5 moet groter zijn dan 3"); assertFalse(2 == 3, "2 mag niet gelijk zijn aan 3"); assertTrue(true, "true moet true zijn"); } // Hoofdfunctie om alle tests uit te voeren int main() { TestSuite math_suite("Wiskunde Tests"); ADD_TEST(math_suite, TestAddition); ADD_TEST(math_suite, TestMultiplication); ADD_TEST(math_suite, TestDivision); ADD_TEST(math_suite, TestBooleanAssertions); math_suite.runAll(); return 0; } ``` ## Uitgebreide rapportage-uitvoer ```cpp // advanced_reporting.h #include <chrono> class AdvancedTestSuite : public TestSuite { private: std::chrono::high_resolution_clock::time_point start_time; public: AdvancedTestSuite(const std::string& name) : TestSuite(name) {} void runAll() { start_time = std::chrono::high_resolution_clock::now(); std::cout << "🧪 TESTSUITE: " << suite_name << std::endl; std::cout << "═════════════════════════════════════════" << std::endl; int passed_count = 0; int total_count = test_cases.size(); for (auto test_case : test_cases) { auto test_start = std::chrono::high_resolution_clock::now(); test_case->run(); auto test_end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(test_end - test_start); if (test_case->isPassed()) { std::cout << "✅ PASS: " << test_case->getName() << " (" << duration.count() << " μs)" << std::endl; passed_count++; } else { std::cout << "❌ FAIL: " << test_case->getName() << " (" << duration.count() << " μs)" << std::endl; std::cout << " 📝 " << test_case->getFailureMessage() << std::endl; } } auto end_time = std::chrono::high_resolution_clock::now(); auto total_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time); std::cout << "═════════════════════════════════════════" << std::endl; std::cout << "📊 SAMENVATTING:" << std::endl; std::cout << " Geslaagd: " << passed_count << "/" << total_count << std::endl; std::cout << " Tijd: " << total_duration.count() << " ms" << std::endl; if (passed_count == total_count) { std::cout << "🎉 ALLE TESTS GESLAAGD!" << std::endl; } else { std::cout << "💥 " << (total_count - passed_count) << " TEST(S) GEFAALD!" << std::endl; } std::cout << std::endl; } }; ``` ## Compilatie en uitvoer ```bash # Compileren g++ -std=c++11 -o tests example_tests.cpp # Uitvoeren ./tests ``` **Verwachte uitvoer:** ``` 🧪 TESTSUITE: Wiskunde Tests ═════════════════════════════════════════ ✅ PASS: TestAddition (45 μs) ✅ PASS: TestMultiplication (32 μs) ✅ PASS: TestDivision (28 μs) ✅ PASS: TestBooleanAssertions (15 μs) ═════════════════════════════════════════ 📊 SAMENVATTING: Geslaagd: 4/4 Tijd: 120 ms 🎉 ALLE TESTS GESLAAGD! ``` ## Belangrijke kenmerken: 1. **Testgevalbeheer**: Hiërarchische structuur met TestSuite en TestCase 2. **Assertiebehandeling**: Verschillende assert-types (true, false, equals, exceptions) 3. **Rapportage**: Gedetailleerde uitvoer met succes/falen en timing 4. **Uitbreidbaar**: Eenvoudig nieuwe asserties en rapportagefuncties toe te voegen 5. **Gebruiksvriendelijk**: Macro's voor eenvoudige testdefinitie Dit raamwerk biedt een solide basis die je verder kunt uitbreiden met functies zoals setup/teardown, testfixtures, parallel testen, of XML-rapportage!