相关代码,来自UnitTest++/TestRunner.h
:
class TestRunner
{
public:
explicit TestRunner(TestReporter& reporter);
~TestRunner();
template <class Predicate>
int RunTestsIf(TestList const& list, char const* suiteName,
const Predicate& predicate, int maxTestTimeInMs) const
{
Test* curTest = list.GetHead();
while (curTest != 0)
{
if (IsTestInSuite(curTest,suiteName) && predicate(curTest))
{
RunTest(m_result, curTest, maxTestTimeInMs);
}
curTest = curTest->next;
}
return Finish();
}
private:
TestReporter* m_reporter;
TestResults* m_result;
Timer* m_timer;
int Finish() const;
bool IsTestInSuite(const Test* const curTest, char const* suiteName) const;
void RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const;
};
这是我试图修改的谓词类,让它做我想做的事情:
class ListFilterRemember {
char **list;
int n;
Test **testsAlreadyRun;
int index_tar;
int max_allocd;
public:
ListFilterRemember(char **list_, int count) {
int testCount = 0;
Test* curTest = Test::GetTestList().GetHead();
while (curTest != 0) {
testCount++;
}
list = list_; n = count; max_allocd = testCount;
testsAlreadyRun = new Test *[max_allocd];
index_tar = 0;
}
bool operator()(const Test* const t) const {
for (int i=0;i<index_tar;++i) {
if (testsAlreadyRun[i] == t) { return false; }
}
for (int i=0;i<n;++i) {
std::string dot_cpp_appended = std::string(list[i]) + ".cpp";
if (!strcasecmp(t->m_details.testName, list[i]) ||
!strcasecmp(t->m_details.suiteName, list[i]) ||
!strcasecmp(t->m_details.filename, list[i]) ||
!strcasecmp(t->m_details.filename, dot_cpp_appended.c_str()) || (
filename_dir_prefix_len < (int)strlen(t->m_details.filename) && ( // ensure the ptr arith in next 2 lines doesn't go out of bounds
!strcasecmp(t->m_details.filename+filename_dir_prefix_len, list[i]) ||
!strcasecmp(t->m_details.filename+filename_dir_prefix_len, dot_cpp_appended.c_str())
)
) || (
std::string::npos != findCaseInsensitive(t->m_details.testName,list[i])
)
) {
// erring on the side of matching more tests
//printf(" running\n");
if (index_tar >= max_allocd) throw std::runtime_error("Did not allocate! Segfault here.");
testsAlreadyRun[index_tar] = (Test *)t;
index_tar += 1;
return true;
}
}
//printf(" not running\n");
return false;
}
~ListFilterRemember() {
delete[] testsAlreadyRun;
}
};
你看到它在TestRunner.h
中定义的方式附加了一个const限定符,这使得我的operator ()
函数无法对成员变量进行更改。我需要进行这些更改,以便记住我已经运行了哪些测试,所以我不再运行它们。可能存在再次运行风险的原因是我打算多次运行RunTestsIf()
。
我在命令行输入一个测试列表,根据名称指定我想要运行的测试。这就是所有字符串匹配代码的用途。我仍然想要使用它们,但这次我想改进它,以便我指定的测试将按照我指定的顺序运行。为了做到这一点,我必须移动测试运行器,以便我循环我的指定的测试列表并逐一进行匹配。
想法?我会在UnitTest ++代码中修改const,但如果我不需要,我不想破坏它。
答案 0 :(得分:1)
您可以使用mutable
关键字,但测试结构的方式表明测试运行器可能不会重复使用相同的谓词实例,因此您的更改可能会在测试之间丢失。当然,如果发布的代码是整个测试运行器,那么它似乎每次调用相同的Predicate
实例。
答案 1 :(得分:0)
通常,您希望单元测试具有一组确定性的测试对象。这可能更接近集成测试。不一定是坏事,只要确保先测试较小的位。
话虽这么说,UnitTest ++的设计很小,很容易修改。我会扩展或包装它以满足您的需求,但不会破坏现有的功能。