Skip to content

Commit 13b6788

Browse files
authored
Handle flaky tests (#206)
1 parent 28b6e09 commit 13b6788

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ if (NOT WIN32)
55
target_link_libraries(run_test PUBLIC OpenMP::OpenMP_CXX)
66
endif()
77
target_link_libraries(run_test PUBLIC perf_lib layers_lib)
8-
target_link_libraries(run_test PUBLIC gtest_main)
8+
target_link_libraries(run_test PUBLIC gtest)
99
target_link_libraries(run_test PUBLIC ReadLib)
1010
target_link_libraries(run_test PUBLIC reader_lib)
1111

1212

13+
target_include_directories(run_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
1314
target_include_directories(run_test PRIVATE "${CMAKE_SOURCE_DIR}/app/ReaderImage")
1415

1516
if (NOT CMAKE_BUILD_TYPE)

test/inference/test_inference.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "layers/OutputLayer.hpp"
1313
#include "layers/PoolingLayer.hpp"
1414
#include "layers/SplitLayer.hpp"
15+
#include "utils/flaky_test_runner.hpp"
1516

1617
using namespace it_lab_ai;
1718

@@ -487,7 +488,7 @@ TEST(bfs, check_struct_layer_added) {
487488
ASSERT_EQ(tmp, res);
488489
}
489490

490-
TEST(bfs, check_struct_graph_split) {
491+
FLAKY_TEST(bfs, check_struct_graph_split) {
491492
std::vector<std::vector<std::pair<int, int>>> split = {
492493
{{12, 0}, {13, 0}, {14, 0}}};
493494
Graph graph(151, split);
@@ -565,4 +566,5 @@ TEST(bfs, check_struct_graph_split) {
565566
std::vector<int> tmp = *output.as<int>();
566567
std::vector<int> res(36, 81);
567568
ASSERT_EQ(tmp, res);
568-
}
569+
}
570+
FLAKY_END_TEST

test/main.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <cstdlib>
4+
#include <cstring>
5+
#include <iostream>
6+
7+
int main(int argc, char** argv) {
8+
::testing::InitGoogleTest(&argc, argv);
9+
10+
const char* flaky_disabled = std::getenv("DISABLE_FLAKY_TESTS");
11+
bool flaky_enabled =
12+
(flaky_disabled == nullptr) || (std::strcmp(flaky_disabled, "1") != 0 &&
13+
std::strcmp(flaky_disabled, "true") != 0);
14+
15+
if (flaky_enabled) {
16+
const char* retries = std::getenv("FLAKY_RETRIES");
17+
int retry_count = retries ? std::atoi(retries) : 10;
18+
std::cout << "Flaky test support enabled. Max retries: " << retry_count
19+
<< std::endl;
20+
std::cout << "Use FLAKY_TEST/FLAKY_TEST_F macros to create flaky tests."
21+
<< std::endl;
22+
}
23+
24+
return RUN_ALL_TESTS();
25+
}

test/utils/flaky_test_runner.hpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#pragma once
2+
3+
#include <gtest/gtest.h>
4+
5+
#include <cstdlib>
6+
#include <cstring>
7+
#include <iostream>
8+
9+
namespace test_utils {
10+
11+
static int getFlakyRetries() {
12+
const char* retry_env = std::getenv("FLAKY_RETRIES");
13+
if (retry_env != nullptr) {
14+
try {
15+
int retries = std::stoi(retry_env);
16+
return std::max(1, std::min(retries, 100));
17+
} catch (const std::exception&) {
18+
return 10;
19+
}
20+
}
21+
return 10;
22+
}
23+
24+
static bool isFlakyTestsEnabled() {
25+
const char* disabled = std::getenv("DISABLE_FLAKY_TESTS");
26+
if (disabled == nullptr) {
27+
return true;
28+
}
29+
return std::strcmp(disabled, "1") != 0 && std::strcmp(disabled, "true") != 0;
30+
}
31+
32+
template <typename TestFunc>
33+
void runFlakyTest(const char* test_name, TestFunc test_func) {
34+
if (!isFlakyTestsEnabled()) {
35+
test_func();
36+
return;
37+
}
38+
39+
int max_retries = getFlakyRetries();
40+
41+
for (int attempt = 1; attempt <= max_retries; ++attempt) {
42+
try {
43+
if (attempt > 1) {
44+
std::cout << "[FLAKY RETRY " << attempt << "/" << max_retries << "] "
45+
<< test_name << std::endl;
46+
}
47+
48+
test_func();
49+
50+
if (attempt > 1) {
51+
std::cout << "[FLAKY SUCCESS] " << test_name << " passed on attempt "
52+
<< attempt << std::endl;
53+
}
54+
return;
55+
56+
} catch (...) {
57+
if (attempt == max_retries) {
58+
std::cout << "[FLAKY EXHAUSTED] " << test_name << " failed after "
59+
<< max_retries << " attempts" << std::endl;
60+
throw;
61+
} else if (attempt == 1) {
62+
std::cout << "[FLAKY FAILED] " << test_name << " failed on attempt "
63+
<< attempt << ", retrying..." << std::endl;
64+
}
65+
}
66+
}
67+
}
68+
69+
#define FLAKY_TEST(test_case_name, test_name) \
70+
TEST(test_case_name, test_name) { \
71+
auto flaky_test_body = []()
72+
73+
#define FLAKY_TEST_F(test_fixture, test_name) \
74+
TEST_F(test_fixture, test_name) { \
75+
auto flaky_test_body = [this]()
76+
77+
#define FLAKY_END_TEST \
78+
; \
79+
test_utils::runFlakyTest( \
80+
testing::UnitTest::GetInstance()->current_test_info()->name(), \
81+
flaky_test_body); \
82+
}
83+
84+
}

0 commit comments

Comments
 (0)