#pragma once ///////////////////////////////////////////////////////////////////// // DemoReqs.h - Demonstrate Project #1 Requirements // // ver 1.1 using the single-user TestHarness // // // // Jim Fawcett, CSE687-Object Oriented Design, Fall 2018 // ///////////////////////////////////////////////////////////////////// /* * Package Operations: * ------------------- * DemoReqs provides seven of the eleven required tests. These run in * The single-user TestHarness, which Project #1 develops. * * All tests are defined in this DemoReqs.h file. They are executed in * the main function in DemoReqs.cpp. * * Notes: * - Each test contains, in comments, a Test Description and * Test Procedure, intended to be a sample to help you complete * Project #1 Requirements #10 and #11. * - This package uses the single-user TestHarness, defined in * TestUtilitiesDemo, to test itself. * * Required Files: * --------------- * DemoReqs.h, DemoReqs.cpp * TestUtilitiesDemo.h, TestUtilitiesDemo.cpp * FileSystem.h, FileSystem.cpp * * Maintenance History: * -------------------- * ver 1.1 : 04 Sep 2018 * - added additional tests for Req #5 * ver 1.0 : 03 Sep 2018 * - first release */ #include #include #include #include "../TestUtilities/TestUtilitiesDemo.h" #include "../StringUtilities/StringUtilities.h" #include "FileSystem.h" namespace UtilitiesTest { using Path = std::string; using Message = std::string; using Line = size_t; using File = std::string; using Files = std::vector; class TestReq1 : public Utilities::ITest { /* * Test Description: * Demonstrates use of C++ * Test Procedure: * - Displays C++ files in project directory */ private: const std::string path_; public: TestReq1(const std::string& path) : path_(path) {} ~TestReq1() { std::cout << "\n deleting TestReq1"; } bool test() { Message msg = "Req #1 - Use C++"; Path path = path_ + "/TestUtilities"; return Utilities::TestHelpers::showDirContents(path, msg); } }; class TestReq2a : public Utilities::ITest { /* * Test Description: * Demonstrates use of C++ streams * Test Procedure: * - Displays lines of project source code that use iostream. * - To insure that std streams are used for ALL output * requires code inspection. */ private: const std::string path_; public: TestReq2a(const std::string& path) : path_(path) {} ~TestReq2a() { std::cout << "\n deleting TestReq2a"; } bool test() { Message msg = "Req #2a - use std::streams - see line 15"; Path fileSpec = path_ + "/TestUtilities/TestUtilitiesDemo.cpp"; return Utilities::TestHelpers::showFileLines(fileSpec, 1, 20, msg); } }; class TestReq2b : public Utilities::ITest { /* * Test Description: * Demonstrates use of C++ new and delete operators * Test Procedure: * - Displays lines of project source code that use new * and std::shared-ptr which will use delete when out * of scope. * - To insure no use of malloc or free requires code * inspection or more advanced test tool with text * finder capability. */ private: const std::string path_; public: TestReq2b(const std::string& path) : path_(path) {} ~TestReq2b() { std::cout << "\n deleting TestReq2b"; } bool test() { Message msg = "Req #2b - use new and delete"; Path fileSpec = path_ + "/TestUtilities/TestUtilitiesDemo.cpp"; return Utilities::TestHelpers::showFileLines(fileSpec, 102, 111, msg); } }; class TestReq3 : public Utilities::ITest { /* * Test Description: * Demonstrates that tests implement ITest interface * Test Procedure: * - Displays lines of project source code where tests * are defined. */ private: const std::string path_; public: TestReq3(const std::string& path) : path_(path) {} ~TestReq3() { std::cout << "\n deleting TestReq3"; } bool test() { Message msg = "Req #3 - tests implement ITest interface"; Path fileSpec = path_ + "/TestUtilities/TestUtilitiesDemo.cpp"; return Utilities::TestHelpers::showFileLines(fileSpec, 25, 32, msg); } }; class TestReq4a : public Utilities::ITest { /* * Test Description: * Demonstrates use of test container in test framework * Test Procedure: * - Displays lines of project source code where container * is defined. */ private: const std::string path_; public: TestReq4a(const std::string& path) : path_(path) {} ~TestReq4a() { std::cout << "\n deleting TestReq4a"; } bool test() { Message msg = "Req #4a - provides test container - see line 119 and line 126"; Path fileSpec2 = path_ + "/TestUtilities/TestUtilitiesDemo.h"; return Utilities::TestHelpers::showFileLines(fileSpec2, 112, 127, msg); } }; class TestReq4b : public Utilities::ITest { /* * Test Description: * Demonstrates use of test container in test framework * Test Procedure: * - Displays lines of this demo where tests are registered * to be placed in test container. */ private: const std::string path_; public: TestReq4b(const std::string& path) : path_(path) {} ~TestReq4b() { std::cout << "\n deleting TestReq4b"; } bool test() { Message msg = "Req #4b - provides test container - shows where this demo's tests are registered"; Path fileSpec = path_ + "/DemoSomeReqs/DemoReqs.cpp"; return Utilities::TestHelpers::showFileLines(fileSpec, 34, 59, msg); } }; class TestPasses : public Utilities::ITest { public: bool test() { return true; } virtual ~TestPasses() { std::cout << "\n -- deleting TestPasses"; } }; class TestFails : public Utilities::ITest { public: bool test() { return false; } ~TestFails() { std::cout << "\n -- deleting TestFails"; } }; class TestThrows : public Utilities::ITest { public: bool test() { std::exception ex("\n -- this test always throws -- "); throw ex; } ~TestThrows() { std::cout << "\n -- deleting TestThrows"; } }; class TestReq5 : public Utilities::ITest { /* * Test Description: * Demonstrates execution of tests in try-catch block * Test Procedure: * - Displays lines of project source code where tests are * run inside try catch block. * - runs tests that: * 1. always passes - show that tests that succeed are correctly reported * 2. always fails - show that tests that fail are correctly reported * 3. always throws - show that exception causes failure report without * without stopping succeeding test executions * * Note: * - This test uses a TestHarness instance to run tests in a test * that will be run by the TestHarness. Mind-bending :-) */ private: const std::string path_; public: TestReq5(const std::string& path) : path_(path) {} ~TestReq5() { std::cout << "\n deleting TestReq5"; } bool test() { Utilities::Cosmetic cos_; // show code with try-catch block Message msg = "Req #5 - function that executes tests within try-catch block"; Path fileSpec = path_ + "/TestUtilities/TestUtilitiesDemo.h"; bool t1 = Utilities::TestHelpers::showFileLines(fileSpec, 81, 97, msg); // use that code to run self tests Utilities::TestExecutive te; using SPtr = std::shared_ptr; std::cout << "\n using test framework to run test that always passes"; SPtr pTt2(new TestPasses); te.registerTest(pTt2, "TestPasses"); bool t2 = te.doTests(); te.clearTests(); std::cout << "\n using test framework to run test that always fails"; SPtr pTt3(new TestFails); te.registerTest(pTt3, "TestFails"); bool t3 = te.doTests(); te.clearTests(); std::cout << "\n using test framework to run test that always throws"; SPtr pTt4(new TestThrows); te.registerTest(pTt4, "TestThrows"); bool t4 = te.doTests(); te.clearTests(); return (t1 == true && t2 == true && t3 == false && t4 == false); } }; }