6 #include "../tunit_export.h"
22 template <
typename test_
class_t>
23 class test_class_attribute;
36 unit_test(std::unique_ptr<xtd::tunit::event_listener>
event_listener,
int argc,
char* argv[]) noexcept : arguments(argv + 1, argv + argc), name_(get_filename(argv[0])), event_listener_(std::move(
event_listener)) {}
45 if (parse_arguments(arguments))
49 std::vector<std::string> tests;
53 return list_tests(tests);
57 std::random_device rd;
59 std::shuffle(test_classes().begin(), test_classes().
end(),
g);
67 unit_test_initialize();
70 start_time_point_ = std::chrono::high_resolution_clock::now();
74 end_time_point_ = std::chrono::high_resolution_clock::now();
81 }
catch(
const std::exception&) {
96 int repeat_iteration() const noexcept {
return repeat_iteration_;}
102 size_t test_cases_count() const noexcept {
104 for (
auto test_class : test_classes())
105 if (test_class.test()->test_count())
110 size_t test_count() const noexcept {
112 for (
auto test_class : test_classes())
113 count += test_class.test()->test_count();
117 size_t aborted_test_count() const noexcept {
119 for (
auto& test_class : test_classes())
120 for (
auto& test : test_class.test()->tests())
125 std::vector<std::string> aborted_test_names() const noexcept {
126 std::vector<std::string> names;
127 for (
auto& test_class : test_classes())
128 for (
auto& test : test_class.test()->tests())
129 if (
settings::default_settings().is_match_test_name(test_class.test()->name(), test.name()) && test.aborted()) names.push_back(test_class.test()->name() +
"." + test.name());
133 std::chrono::milliseconds elapsed_time() const noexcept {
134 using namespace std::chrono_literals;
135 if (start_time_point_.time_since_epoch() == 0ms && end_time_point_.time_since_epoch() == 0ms)
return 0ms;
136 if (end_time_point_.time_since_epoch() == 0ms)
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time_point_);
137 return std::chrono::duration_cast<std::chrono::milliseconds>(end_time_point_ - start_time_point_);
140 size_t ignored_test_count() const noexcept {
142 for (
auto test_class : test_classes())
143 count += test_class.test()->ignored_test_count();
147 std::vector<std::string> ignored_test_names() const noexcept {
148 std::vector<std::string> names;
149 for (
auto& test_class : test_classes())
150 for (
auto& test : test_class.test()->tests())
151 if (
settings::default_settings().is_match_test_name(test_class.test()->name(), test.name()) && test.ignored()) names.push_back(test_class.test()->name() +
"." + test.name());
155 size_t failed_test_count() const noexcept {
157 for (
auto& test_class : test_classes())
158 for (
auto& test : test_class.test()->tests())
163 std::vector<std::string> failed_test_names() const noexcept {
164 std::vector<std::string> names;
165 for (
auto& test_class : test_classes())
166 for (
auto& test : test_class.test()->tests())
167 if (
settings::default_settings().is_match_test_name(test_class.test()->name(), test.name()) && test.failed()) names.push_back(test_class.test()->name() +
"." + test.name());
171 size_t succeed_test_count() const noexcept {
173 for (
auto& test_class : test_classes())
174 for (
auto& test : test_class.test()->tests())
179 std::vector<std::string> succeed_test_names() const noexcept {
180 std::vector<std::string> names;
181 for (
auto& test_class : test_classes())
182 for (
auto& test : test_class.test()->tests())
183 if (
settings::default_settings().is_match_test_name(test_class.test()->name(), test.name()) && test.succeed()) names.push_back(test_class.test()->name() +
"." + test.name());
188 virtual int list_tests(
const std::vector<std::string>& tests) {
192 virtual bool parse_arguments(
const std::vector<std::string>& args) {
193 for (
auto arg : args) {
211 template <
typename test_
class_t>
219 void unit_test_cleanup() {
222 void unit_test_initialize() {
225 static std::vector<xtd::tunit::registered_test_class>& test_classes() {
226 static std::vector<xtd::tunit::registered_test_class> test_classes;
230 std::string get_filename(
const std::string& path) {
231 std::string filename = path;
232 const size_t last_slash_idx = filename.find_last_of(
"\\/");
233 if (std::string::npos != last_slash_idx)
234 filename.erase(0, last_slash_idx + 1);
236 const size_t period_idx = filename.rfind(
'.');
237 if (std::string::npos != period_idx)
238 filename.erase(period_idx);
242 std::string
to_string(
const std::chrono::milliseconds& ms) {
243 std::stringstream ss;
247 ss << ms.count() / 1000 <<
"." << std::setfill(
'0') << std::setw(3) << ms.count() % 1000;
251 std::string
to_string(
const std::chrono::time_point<std::chrono::system_clock>& time) {
252 std::time_t time_t = std::chrono::system_clock::to_time_t(time);
253 std::tm tm = *std::localtime(&time_t);
254 std::stringstream ss;
255 ss << tm.tm_year + 1900 <<
"-" << std::setfill(
'0') << std::setw(2) << tm.tm_mon <<
"-" << std::setfill(
'0') << std::setw(2) << tm.tm_mday;
256 ss <<
"T" << std::setfill(
'0') << std::setw(2) << tm.tm_hour <<
":" << std::setfill(
'0') << std::setw(2) << tm.tm_min <<
":" << std::setfill(
'0') << std::setw(2) << tm.tm_sec;
261 std::stringstream ss;
262 if (test.not_started() || test.ignored()) ss <<
"notrun";
268 std::stringstream ss;
271 ss <<
"Expected: " << test.expect() <<
"�x0A;";
272 ss <<
"But was : " << test.actual();
277 std::stringstream ss;
280 ss <<
"Expected: " << test.expect() << std::endl;
281 ss <<
"But was : " << test.actual();
288 file <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
289 file <<
"<testsuites tests=\"" << test_count() <<
"\" failures=\"" << failed_test_count() <<
"\" disabled=\"" << ignored_test_count() <<
"\" errors=\"" << 0 <<
"\" timestamp=\"" <<
to_string(
xtd::tunit::settings::default_settings().start_time()) <<
"\" time=\"" <<
to_string(elapsed_time()) <<
"\" name=\"" << name_ <<
"\">" << std::endl;
290 for (
auto& test_class : test_classes()) {
291 file <<
" <testsuite name=\"" << test_class.test()->name() <<
"\" tests=\"" << test_class.test()->test_count() <<
"\" failures=\"" << test_class.test()->failed_test_count() <<
"\" disabled=\"" << test_class.test()->ignored_test_count() <<
"\" error=\"" << test_class.test()->failed_test_count() <<
"\" time=\"" <<
to_string(test_class.test()->elapsed_time()) <<
"\">" << std::endl;
292 for (
auto& test : test_class.test()->tests()) {
293 file <<
" <testcase name=\"" << test.name() <<
"\" status=\"" << status_to_string(test) <<
"\" time=\"" <<
to_string(test.elapsed_time()) <<
"\" classname=\"" << test_class.test()->name() <<
"\"";
295 file <<
" />" << std::endl;
297 file <<
">" << std::endl;
298 file <<
" <failure message=\"" << message_to_string(test) <<
"\" type= \"" <<
"\">" <<
"<![CDATA[" << cdata_message_to_string(test) <<
"]]></failure>" << std::endl;
299 file <<
" </testcase>" << std::endl;
302 file <<
" </testsuite>" << std::endl;
304 file <<
"</testsuites>" << std::endl;
309 std::vector<std::string> arguments;
310 std::string name_ =
"AllTests";
311 std::unique_ptr<xtd::tunit::event_listener> event_listener_;
312 std::chrono::high_resolution_clock::time_point end_time_point_;
313 int repeat_iteration_ = 0;
314 std::chrono::high_resolution_clock::time_point start_time_point_;
virtual const xtd::ustring & get_file_name() const
Gets the file name that contains the code that is executing. This information is typically extracted ...
virtual uint32_t get_file_line_number() const
Gets the line number in the file that contains the code that is executing. This information is typica...
static stack_frame empty() noexcept
Return an empty stack frame.
The base class for assert.
Definition: base_assert.h:25
Represent the event listener class. Unit test call theses events when unit tests are processing.
Definition: event_listener.h:23
Represents the registered test class.
Definition: registered_test_class.h:19
std::string output_xml_path() const noexcept
Gets output xml path.
Definition: settings.h:94
int exit_status() const noexcept
Gets exit status.
Definition: settings.h:46
std::chrono::time_point< std::chrono::system_clock > end_time() const noexcept
Gets unit test end time.
Definition: settings.h:140
static xtd::tunit::settings & default_settings() noexcept
Get default settings instance.
bool also_run_ignored_tests() const noexcept
Gets also run ignored test.
Definition: settings.h:36
bool shuffle_test() const noexcept
Gets shuffle tests.
Definition: settings.h:103
bool output_xml() const noexcept
Gets output xml.
Definition: settings.h:86
bool show_duration() const noexcept
Gets if show duration for each test.
Definition: settings.h:132
bool output_color() const noexcept
Gets output color.
Definition: settings.h:78
const std::string & filter_tests() const noexcept
Gets filter tests.
Definition: settings.h:57
void repeat_tests(int repeat_tests) noexcept
Sets repeat tests count.
Definition: settings.h:128
int random_seed() const noexcept
Gets random seed value.
Definition: settings.h:113
bool list_tests() const noexcept
Gets list tests.
Definition: settings.h:70
int repeat_test() const noexcept
Gets repeat tests count.
Definition: settings.h:123
Definition: test_class_attribute.h:14
Definition: test_class.h:25
tunit_event_args is the base class for classes containing event data.
Definition: tunit_event_args.h:20
The template class.
Definition: unit_test.h:32
int run()
Runs all tests in this UnitTest object and prints the result.
Definition: unit_test.h:44
Contains xtd::tunit::event_listener class.
#define tunit_export_
Define shared library export.
Definition: tunit_export.h:13
std::string to_string(const value_t &value, const std::string &fmt, const std::locale &loc)
Convert a specified value into a string with specified format and locale.
Definition: to_string.h:37
The xtd namespace contains all fundamental classes to access Hardware, Os, System,...
Definition: system_report.h:17
Contains xtd::tunit::registered_test_class class.
Contains xtd::tunit::settings class.