我有一个具有execute()函数的类。执行execute() 该函数仅在调用Terminate()函数时停止。我要测试execute()函数。
class Process{
public:
void execute(){ // start execution until terminate() is called.. }
void terminate(){ //stop the processing of execute()... }
}
我的单元测试用例如下。我正在使用MSTest。
TEST_METHOD(StartTest)
{
Process p;
bool isRunning = true;
std::thread th([&](){
p.execute();
isRunning = false;
});
th.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
Assert::isTrue(isRunning);
}
如果使用线程是一种好习惯,那么我应该关闭测试用例中的线程,而不是将其与主线程分离吗?
更好的建议是可取的。
答案 0 :(得分:3)
首先应该同步对isRunning
的访问。在您的示例中,您只需使用std::atomic<bool>
即可完成操作。
免责声明:自从我完成了任何类型的serios多线程以来,已经有一段时间了,因此请花点时间。另外,除了检查其可编译性之外,我还没有测试过代码。
这就是我要开始的地方:
auto test()
{
std::condition_variable cv{};
std::mutex m{};
Process p{};
bool isRunning{true};
std::thread th([&] {
p.execute();
{
std::lock_guard<std::mutex> lk{m};
isRunning = false;
}
cv.notify_one();
});
{
std::unique_lock<std::mutex> lk{m};
// expect timeout
Assert::isFalse(cv.wait_for(lk, std::chrono::milliseconds(300),
[&] () { return !isRunning; }));
}
p.terminate();
{
std::unique_lock<std::mutex> lk{m};
// expect condition to change
Assert::isTrue(cv.wait_for(lk, std::chrono::milliseconds(300),
[&] () { return !isRunning; }));
}
th.join();
}
通过这种方式,您既可以检查execute
是否被阻止,又可以检查terminate
是否终止,则可以更大的灵活性。如果execute
提早解除阻止,您就不必等待整个超时,而terminate
则有一个摆动要等待另一个线程结束,并尽快解除阻塞。
如果terminate()无法停止执行,则该线程将继续 在这个测试用例结束后他的处决?
如果terminate
没有停止执行,则第二个wait_for
在超时返回false
之后结束,并且断言启动。我不知道您使用的测试框架是什么, Assert
会这样做。
如果将执行返回到test
,则测试将在join
上阻塞,直到线程完成
如果引发异常,则不调用join
,如果线程尚未结束,则在th
的析构函数中调用std::terminate
。可以使用try catch
如果它强制退出(例如调用std::terminate
),那么...好吧...您的程序结束,无论
这确实是您需要分析的问题。如果terminate
在您的等待间隔内未能停止execute
,这完全取决于您要做什么。
如果可以在test
中等待,那么您要做的就是确保调用了join
。正如我所说的,try catch
可以解决。
如果您想结束当前测试,但是仍然可以继续运行线程,那么如果terminate
无法结束线程,则需要分离线程。
如果您想杀死线程,那么...那是不可能的。您可以改为通过std::terminate
杀死整个应用。