运行 来自单元测试用例的线程是一个好习惯吗?
Is it a good practice to ran a thread from a unit test case?
我有 class,它有一个 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);
}
如果使用线程是一个好习惯,我应该关闭测试用例中的线程而不是将其与主线程分离吗?
还有更好的建议值得赞赏。
首先应该同步对 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
,您可以摆动等待另一个线程完成,您会尽快解除阻塞。
If terminate() fails to stop the execution, will th thread continue
his execution after the end of this test case?
如果 terminate
没有停止执行,那么第二个 wait_for
在超时返回后结束 false
并且断言开始。我不知道你使用什么测试框架以及 Assert
的作用。
如果它 returns 执行到 test
那么测试将阻塞在 join
直到线程完成
如果它抛出异常那么join
不会被调用并且在th
的析构函数中如果线程还没有结束std::terminate
将被调用.这可以用 try catch
来改变
如果它强制退出(例如调用 std::terminate
)那么......好吧......不管怎样你的程序都会结束
这确实是你需要分析的问题。如果 terminate
在您的等待间隔内未能停止 execute
,这完全取决于您想做什么。
如果您可以在 test
内等待,那么您需要做的就是确保调用 join
。正如我所说,这可以用 try catch
.
解决
如果你想结束当前测试,但线程仍在继续,那么如果 terminate
未能结束它,你需要分离线程。
如果你想终止线程那么......那是不可能的。您可以改为通过 std::terminate
.
终止整个应用程序
我有 class,它有一个 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);
}
如果使用线程是一个好习惯,我应该关闭测试用例中的线程而不是将其与主线程分离吗?
还有更好的建议值得赞赏。
首先应该同步对 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
,您可以摆动等待另一个线程完成,您会尽快解除阻塞。
If terminate() fails to stop the execution, will th thread continue his execution after the end of this test case?
如果 terminate
没有停止执行,那么第二个 wait_for
在超时返回后结束 false
并且断言开始。我不知道你使用什么测试框架以及 Assert
的作用。
如果它 returns 执行到
test
那么测试将阻塞在join
直到线程完成如果它抛出异常那么
join
不会被调用并且在th
的析构函数中如果线程还没有结束std::terminate
将被调用.这可以用try catch
来改变
如果它强制退出(例如调用
std::terminate
)那么......好吧......不管怎样你的程序都会结束
这确实是你需要分析的问题。如果 terminate
在您的等待间隔内未能停止 execute
,这完全取决于您想做什么。
如果您可以在
test
内等待,那么您需要做的就是确保调用join
。正如我所说,这可以用try catch
. 解决
如果你想结束当前测试,但线程仍在继续,那么如果
terminate
未能结束它,你需要分离线程。如果你想终止线程那么......那是不可能的。您可以改为通过
std::terminate
. 终止整个应用程序