Skip to content

Commit a1d8e07

Browse files
author
Jesse
committed
started writing unit tests
1 parent cbcd5e7 commit a1d8e07

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
2+
cmake_policy(VERSION 3.2)
3+
option(ARGPARSE_TEST_ENABLE "Build unit tests" ON)
4+
5+
set(ARGPARSE_VERSION "0.9.9")
6+
project(argparse VERSION ${ARGPARSE_VERSION} LANGUAGES CXX)
7+
enable_testing()
8+
9+
add_library(argparse INTERFACE)
10+
target_include_directories(argparse INTERFACE .)
11+
12+
if(ARGPARSE_TEST_ENABLE)
13+
add_executable(tests tests.cpp)
14+
add_test(
15+
NAME tests
16+
COMMAND $<TARGET_FILE:tests>)
17+
target_link_libraries(tests PRIVATE argparse)
18+
endif(ARGPARSE_TEST_ENABLE)

tests.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include "argparse.h"
2+
3+
#include <functional>
4+
#include <iostream>
5+
#include <map>
6+
#include <string>
7+
8+
struct result {
9+
bool pass;
10+
int line;
11+
const char* condition;
12+
const char* msg;
13+
const char* test;
14+
};
15+
16+
#define TASSERT(condition, msg) \
17+
if (!(condition)) { \
18+
return {false, __LINE__, #condition, msg, ""}; \
19+
}
20+
21+
#define TEST(name, code, ...) \
22+
result name() { \
23+
char* argv[] = {#name, ##__VA_ARGS__}; \
24+
int argc = sizeof(argv) / sizeof(argv[0]); \
25+
ArgumentParser parser(#name); \
26+
code return {true, 0, "", "", ""}; \
27+
}
28+
29+
TEST(short_optional_flag_exists,
30+
{
31+
parser.add_argument("-f", "a flag", false);
32+
try {
33+
parser.parse(argc, argv);
34+
} catch (const ArgumentParser::ArgumentNotFound& ex) {
35+
TASSERT(false, ex.what())
36+
}
37+
TASSERT(parser.exists("f"), "flag not found")
38+
},
39+
"-f")
40+
41+
TEST(short_optional_flag_does_not_exist,
42+
{
43+
parser.add_argument("-f", "a flag", false);
44+
try {
45+
parser.parse(argc, argv);
46+
} catch (const ArgumentParser::ArgumentNotFound& ex) {
47+
TASSERT(false, ex.what())
48+
}
49+
TASSERT(!parser.exists("f"), "flag found")
50+
},
51+
"")
52+
53+
TEST(short_required_flag_exists,
54+
{
55+
parser.add_argument("-f", "a flag", true);
56+
try {
57+
parser.parse(argc, argv);
58+
} catch (const ArgumentParser::ArgumentNotFound& ex) {
59+
TASSERT(false, ex.what())
60+
}
61+
TASSERT(parser.exists("f"), "required flag not found")
62+
},
63+
"-f")
64+
65+
TEST(short_required_flag_does_not_exist,
66+
{
67+
parser.add_argument("-f", "a flag", true);
68+
bool failed = false;
69+
try {
70+
parser.parse(argc, argv);
71+
} catch (const ArgumentParser::ArgumentNotFound& ex) {
72+
failed = true;
73+
}
74+
TASSERT(failed, "required flag found")
75+
},
76+
"")
77+
78+
#define TT(name) \
79+
{ #name, name }
80+
using test = std::function<result()>;
81+
std::map<std::string, test> tests{
82+
TT(short_optional_flag_exists), TT(short_optional_flag_does_not_exist),
83+
TT(short_required_flag_exists), TT(short_required_flag_does_not_exist)};
84+
85+
int main(int argc, const char* argv[]) {
86+
std::vector<result> results;
87+
if (argc > 1) {
88+
for (auto i = 1; i < argc; i++) {
89+
auto test = tests.find(argv[i]);
90+
if (test != tests.end()) {
91+
results.push_back(test->second());
92+
results.back().test = test->first.c_str();
93+
}
94+
}
95+
} else {
96+
for (auto& test : tests) {
97+
results.push_back(test.second());
98+
results.back().test = test.first.c_str();
99+
}
100+
}
101+
size_t passed = 0;
102+
for (auto& r : results) {
103+
passed += static_cast<size_t>(r.pass);
104+
std::cout << r.test << ": " << (r.pass ? "pass" : "fail") << std::endl;
105+
if (!r.pass) {
106+
std::cout << "****************************************************"
107+
<< std::endl
108+
<< "Line " << r.line << ": " << r.condition << std::endl
109+
<< r.msg << std::endl
110+
<< "****************************************************"
111+
<< std::endl
112+
<< std::endl;
113+
}
114+
}
115+
std::cout << "Passed: " << passed << "/" << results.size() << std::endl;
116+
return 0;
117+
}

0 commit comments

Comments
 (0)