lernen:doctest
no way to compare when less than two revisions
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | lernen:doctest [2022-05-21 07:20] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== doctest ====== | ||
+ | |||
+ | ===== Unit-Tests ===== | ||
+ | |||
+ | Zum Schreiben von Programmen gehört auch das Testen, ob sie das tun, was sie tun sollen. Unit-Tests überprüfen Programmbausteine. Funktioniert die geschriebene Funktion oder Bibliothek? Erfüllt sie die Anforderungen? | ||
+ | |||
+ | ===== Die Aufgabe ===== | ||
+ | |||
+ | Nehmen wir ein einfaches Programm: | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | std::cout << is_pythagorean_triple(3, | ||
+ | } | ||
+ | </ | ||
+ | Bei einem pythagoräischen Tripel ist das Quadrat der größten (natürlichen) Zahl gleich der Summe der Quadrate der anderen beiden (natürlichen) Zahlen: 3² + 4² = 5². Der Name kommt vom Satz des Pythagoras, ein Dreieck mit den Seitenlängen 3, 4 und 5 (in willkürlichen Einheiten) ist rechtwinklig. | ||
+ | |||
+ | Das Projekt wird in '' | ||
+ | |||
+ | < | ||
+ | cmake_minimum_required(VERSION 3.18) | ||
+ | project(Example) | ||
+ | |||
+ | set(CMAKE_CXX_STANDARD 20) | ||
+ | set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
+ | set(CMAKE_CXX_EXTENSIONS OFF) | ||
+ | |||
+ | add_executable(programm src/ | ||
+ | target_include_directories(programm PRIVATE include) | ||
+ | target_sources(programm PRIVATE src/ | ||
+ | </ | ||
+ | Wir werden es mehrfach übersetzen und testen müssen. Der Header '' | ||
+ | |||
+ | <code cpp> | ||
+ | #pragma once | ||
+ | bool is_pythagorean_triple(int a, int b, int c); | ||
+ | </ | ||
+ | befindet sich im Unterverzeichnis '' | ||
+ | |||
+ | < | ||
+ | mkdir build | ||
+ | cd build | ||
+ | cmake -G "MinGW Makefiles" | ||
+ | cmake --build . | ||
+ | programm | ||
+ | </ | ||
+ | sollte als Ausgabe '' | ||
+ | |||
+ | ===== Tests zuerst ===== | ||
+ | |||
+ | Halt! Zuvor sollte festgelegt werden, was die fehlende Funktion tun soll. Dafür bereiten wir eine Test-Umgebung vor. Wir erweitern '' | ||
+ | |||
+ | < | ||
+ | add_executable(test_programm doctest/ | ||
+ | target_include_directories(test_programm PRIVATE include doctest/ | ||
+ | target_sources(test_programm PRIVATE src/ | ||
+ | </ | ||
+ | Das Hauptprogramm '' | ||
+ | |||
+ | <code cpp> | ||
+ | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN | ||
+ | #include " | ||
+ | </ | ||
+ | Es schließt nur den von der Webseite zu holenden Header '' | ||
+ | |||
+ | <code cpp> | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | TEST_CASE(" | ||
+ | { | ||
+ | CHECK(true == is_pythagorean_triple(3, | ||
+ | CHECK(true == is_pythagorean_triple(5, | ||
+ | } | ||
+ | </ | ||
+ | ===== Roter Test (schlägt fehl) ===== | ||
+ | |||
+ | Eine erste Implementierung (wir überspringen die nullte Näherung '' | ||
+ | |||
+ | <code cpp> | ||
+ | #include " | ||
+ | |||
+ | bool is_pythagorean_triple(int a, int b, int c) | ||
+ | { | ||
+ | return a*a + b*b == c*c; | ||
+ | } | ||
+ | </ | ||
+ | genügt zwar der ersten Anforderung. Die zweite schlägt beim Aufruf des Testprogramms fehl(( | ||
+ | Ich weiß nicht warum. Hängt vermutlich damit zusammen, dass wir uns an Stelle des Satzes von Pythagoras die Formel a²+b²=c² gemerkt haben. | ||
+ | Wie oft hat deine Lehrerin darauf hingewiesen, | ||
+ | )). Die Beanstandung wird klar und deutlich ausgegeben: | ||
+ | |||
+ | < | ||
+ | ...> | ||
+ | [doctest] doctest version is " | ||
+ | [doctest] run with " | ||
+ | =============================================================================== | ||
+ | ...\pythagorean.test.cpp: | ||
+ | TEST CASE: known triples | ||
+ | |||
+ | ...\pythagorean.test.cpp: | ||
+ | values: CHECK( true == false ) | ||
+ | |||
+ | =============================================================================== | ||
+ | [doctest] test cases: | ||
+ | [doctest] assertions: | ||
+ | [doctest] Status: FAILURE! | ||
+ | </ | ||
+ | ===== Grüner Test (ist bestanden) ===== | ||
+ | |||
+ | Erst durch Umordnen der übernommenen Werte | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | bool is_pythagorean_triple(int a, int b, int c) | ||
+ | { | ||
+ | if (a > c) std:: | ||
+ | if (b > c) std:: | ||
+ | | ||
+ | return a*a + b*b == c*c; | ||
+ | } | ||
+ | </ | ||
+ | wird dieser Test bestanden: | ||
+ | |||
+ | < | ||
+ | [doctest] test cases: | ||
+ | [doctest] assertions: | ||
+ | [doctest] Status: SUCCESS! | ||
+ | </ | ||
+ | ===== Neue Anforderungen ===== | ||
+ | |||
+ | Auch das andere mögliche Ergebnis muss eine boolesche Funktion erfüllen, was sie glücklicherweise tut. Der Test bleibt grün: | ||
+ | |||
+ | <code cpp> | ||
+ | TEST_CASE(" | ||
+ | { | ||
+ | CHECK(false == is_pythagorean_triple(1, | ||
+ | CHECK(false == is_pythagorean_triple(5, | ||
+ | } | ||
+ | </ | ||
+ | Weil (3,4,5) als das pythagoräische Tripel mit den kleinsten Zahlen bekannt ist, müssen wir aber auch die Null ausschließen: | ||
+ | |||
+ | < | ||
+ | TEST_CASE(" | ||
+ | { | ||
+ | CHECK(false == is_pythagorean_triple(0, | ||
+ | CHECK(false == is_pythagorean_triple(-3, | ||
+ | CHECK(false == is_pythagorean_triple(-3, | ||
+ | } | ||
+ | </ | ||
+ | Dieser Test wird erst mit einer weiteren Änderung grün: | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | bool is_pythagorean_triple(int a, int b, int c) | ||
+ | { | ||
+ | if (a < 1 || b < 1 || c < 1) return false; | ||
+ | if (a > c) std:: | ||
+ | if (b > c) std:: | ||
+ | | ||
+ | return a*a + b*b == c*c; | ||
+ | } | ||
+ | </ | ||
+ | < | ||
+ | [doctest] test cases: | ||
+ | [doctest] assertions: | ||
+ | [doctest] Status: SUCCESS! | ||
+ | </ | ||
+ | Sollten weitere Forderungen kommen (nur teilerfremde Zahlen?), sind wir gewappnet. Nebenbei gibt es unendlich viele weitere pythagoräische Tripel, z.B. (5, | ||
+ | |||
+ | ===== CTest ===== | ||
+ | |||
+ | Unabhängig davon, ob wir '' | ||
+ | |||
+ | < | ||
+ | enable_testing() | ||
+ | add_test(test_pyth test_programm) | ||
+ | </ | ||
+ | und dann mit einem der Befehle | ||
+ | |||
+ | < | ||
+ | cmake --build . --target test | ||
+ | ctest | ||
+ | ctest -V | ||
+ | </ | ||
+ | ausführen lassen: | ||
+ | |||
+ | < | ||
+ | Test project .../build | ||
+ | Start 1: test_pyth | ||
+ | 1/1 Test #1: test_pyth ........................ | ||
+ | |||
+ | 100% tests passed, 0 tests failed out of 1 | ||
+ | |||
+ | Total Test time (real) = 0.03 sec | ||
+ | </ | ||
+ | Die Option '' | ||
lernen/doctest.txt · Zuletzt geändert: 2022-05-21 07:20 von 127.0.0.1