55#include < fmt/format.h>
66#include < string>
77#include < utility>
8+ #include < vector>
89
910static std::size_t countFiles (const tests::fs::path& root,
1011 std::string_view extension) {
@@ -20,6 +21,42 @@ static std::size_t countFiles(const tests::fs::path& root,
2021 return count;
2122}
2223
24+ struct TestInfo {
25+ std::string projectName;
26+ std::vector<std::string> testTargets;
27+ bool hasLib = false ;
28+
29+ std::size_t numPassed = 0 ;
30+ std::size_t numFailed = 0 ;
31+ std::size_t numFiltered = 0 ;
32+ };
33+
34+ static std::string expectedTestSummary (const TestInfo& testInfo) {
35+ std::string summary = " Analyzing project dependencies...\n " ;
36+ if (testInfo.hasLib ) {
37+ summary += fmt::format (" Compiling {}(lib) v0.1.0 (<PROJECT>)\n " ,
38+ testInfo.projectName );
39+ }
40+ summary += fmt::format (
41+ " Compiling {}(test) v0.1.0 (<PROJECT>)\n "
42+ " Finished `test` profile [unoptimized + debuginfo] target(s) in "
43+ " <DURATION>s\n " ,
44+ testInfo.projectName );
45+
46+ for (std::string_view testTarget : testInfo.testTargets ) {
47+ summary += fmt::format (" Running unit test src/{0}.cc "
48+ " (cabin-out/test/unit/src/{0}.cc.test)\n " ,
49+ testTarget);
50+ }
51+
52+ summary += fmt::format (
53+ " Ok {} passed; {} failed; {} filtered out; finished in "
54+ " <DURATION>s\n " ,
55+ testInfo.numPassed , testInfo.numFailed , testInfo.numFiltered );
56+
57+ return summary;
58+ }
59+
2360static std::string expectedTestSummary (std::string_view projectName,
2461 bool hasLib) {
2562 std::string summary = " Analyzing project dependencies...\n " ;
@@ -34,7 +71,8 @@ static std::string expectedTestSummary(std::string_view projectName,
3471 " <DURATION>s\n "
3572 " Running unit test src/main.cc "
3673 " (cabin-out/test/unit/src/main.cc.test)\n "
37- " Ok 1 passed; 0 failed; finished in <DURATION>s\n " ;
74+ " Ok 1 passed; 0 failed; 0 filtered out; finished in "
75+ " <DURATION>s\n " ;
3876 return summary;
3977}
4078
@@ -55,8 +93,8 @@ int main() {
5593void test_addition() {
5694 int result = 2 + 2;
5795 if (result != 4) {
58- std::cerr << "Test failed: 2 + 2 = " << result << ", expected 4" << std::endl;
59- std::exit(1);
96+ std::cerr << "Test failed: 2 + 2 = " << result << ", expected 4" <<
97+ std::endl; std:: exit(1);
6098 }
6199 std::cout << "test test addition ... ok" << std::endl;
62100}
@@ -260,4 +298,139 @@ int main() {
260298 const auto outDir = project / " cabin-out" / " test" / " unit" / " lib" ;
261299 expect (tests::fs::is_regular_file (outDir / " lib_only.cc.test" ));
262300 };
301+
302+ " cabin test testname filters single test" _test = [] {
303+ const tests::TempDir tmp;
304+ tests::runCabin ({ " new" , " testname_project" }, tmp.path ).unwrap ();
305+ const auto project = tmp.path / " testname_project" ;
306+ const auto projectPath = tests::fs::weakly_canonical (project).string ();
307+
308+ tests::writeFile (project / " src/main.cc" ,
309+ R"( #include <iostream>
310+
311+ #ifdef CABIN_TEST
312+ void test_function() {
313+ std::cout << "main test function ... ok" << std::endl;
314+ }
315+
316+ int main() {
317+ test_function();
318+ return 0;
319+ }
320+ #else
321+ int main() {
322+ std::cout << "Hello, world!" << std::endl;
323+ return 0;
324+ }
325+ #endif
326+ )" );
327+
328+ tests::writeFile (project / " src/Testname.cc" ,
329+ R"( #include <iostream>
330+
331+ #ifdef CABIN_TEST
332+ void test_function() {
333+ std::cout << "testname test function ... ok" << std::endl;
334+ }
335+
336+ int main() {
337+ test_function();
338+ return 0;
339+ }
340+ #endif
341+ )" );
342+
343+ const auto result =
344+ tests::runCabin ({ " test" , " Testname" }, project).unwrap ();
345+ expect (result.status .success ());
346+ auto sanitizedOut = tests::sanitizeOutput (
347+ result.out , { { projectPath, " <PROJECT>" } }); // NOLINT
348+ expect (sanitizedOut == " testname test function ... ok\n " );
349+ auto sanitizedErr = tests::sanitizeOutput (
350+ result.err , { { projectPath, " <PROJECT>" } }); // NOLINT
351+
352+ expect (sanitizedErr
353+ == expectedTestSummary (TestInfo{ .projectName = " testname_project" ,
354+ .testTargets = { " Testname" },
355+ .numPassed = 1 ,
356+ .numFailed = 0 ,
357+ .numFiltered = 1 }));
358+ };
359+
360+ " cabin test testname filters multiple tests" _test = [] {
361+ const tests::TempDir tmp;
362+ tests::runCabin ({ " new" , " testname_project" }, tmp.path ).unwrap ();
363+ const auto project = tmp.path / " testname_project" ;
364+ const auto projectPath = tests::fs::weakly_canonical (project).string ();
365+
366+ tests::writeFile (project / " src/main.cc" ,
367+ R"( #include <iostream>
368+
369+ #ifdef CABIN_TEST
370+ void test_function() {
371+ std::cout << "main test function ... ok" << std::endl;
372+ }
373+
374+ int main() {
375+ test_function();
376+ return 0;
377+ }
378+ #else
379+ int main() {
380+ std::cout << "Hello, world!" << std::endl;
381+ return 0;
382+ }
383+ #endif
384+ )" );
385+
386+ tests::writeFile (project / " src/TestnameFirst.cc" ,
387+ R"( #include <iostream>
388+
389+ #ifdef CABIN_TEST
390+ void test_function() {
391+ std::cout << "testname first function ... ok" << std::endl;
392+ }
393+
394+ int main() {
395+ test_function();
396+ return 0;
397+ }
398+ #endif
399+ )" );
400+
401+ tests::writeFile (project / " src/TestnameSecond.cc" ,
402+ R"( #include <iostream>
403+
404+ #ifdef CABIN_TEST
405+ void test_function() {
406+ std::cout << "testname second function ... ok" << std::endl;
407+ }
408+
409+ int main() {
410+ test_function();
411+ return 0;
412+ }
413+ #endif
414+ )" );
415+
416+ const auto result =
417+ tests::runCabin ({ " test" , " Testname" }, project).unwrap ();
418+ expect (result.status .success ());
419+
420+ auto sanitizedOut = tests::sanitizeOutput (
421+ result.out , { { projectPath, " <PROJECT>" } }); // NOLINT
422+ expect (sanitizedOut
423+ == " testname first function ... ok\n "
424+ " testname second function ... ok\n " );
425+
426+ auto sanitizedErr = tests::sanitizeOutput (
427+ result.err , { { projectPath, " <PROJECT>" } }); // NOLINT
428+ expect (sanitizedErr
429+ == expectedTestSummary (
430+ TestInfo{ .projectName = " testname_project" ,
431+ .testTargets = { " TestnameFirst" , " TestnameSecond" },
432+ .numPassed = 2 ,
433+ .numFailed = 0 ,
434+ .numFiltered = 1 }));
435+ };
263436}
0 commit comments