C++ 从单元测试用例运行线程是一种好的实践吗?

C++ 从单元测试用例运行线程是一种好的实践吗?,c++,unit-testing,visual-c++,mstest,C++,Unit Testing,Visual C++,Mstest,我有一个类,它有一个execute()函数。execute()的执行 函数仅在调用terminate()函数时停止。我想测试execute()函数 class Process{ public: void execute(){ // start execution until terminate() is called.. } void terminate(){ //stop the processing of execute()... } } 下面给出了我的单元测试用例。

我有一个类,它有一个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
,然后使用它

免责声明:我已经有一段时间没有做任何类型的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();
}
自动测试()
{
std::条件_变量cv{};
std::mutexm{};
过程p{};
布尔正在运行{true};
标准:螺纹th([&]{
p、 执行();
{
std::lock_-guard lk{m};
isRunning=false;
}
cv.通知_one();
});
{
std::unique_lock lk{m};
//预期超时
断言::isFalse(cv.wait_for(lk,std::chrono::毫秒(300),
[&](){return!isRunning;}));
}
p、 终止();
{
std::unique_lock lk{m};
//期望情况改变
断言::isTrue(cv.wait_for(lk,std::chrono::毫秒(300),
[&](){return!isRunning;}));
}
th.join();
}
通过这种方式,您可以检查
执行
是否要阻止,以及
终止
是否要终止,这样您就有了更大的灵活性。如果
execute
提前解除阻止,则不会等待完全超时,而对于
terminate
,您需要等待另一个线程完成,并尽快解除阻止


如果terminate()无法停止执行,线程是否会继续 他在这个测试用例结束后被执行

如果
terminate
没有停止执行,则第二次
等待
在超时返回
false
后结束,断言生效。我不知道您使用什么测试框架,也不知道
Assert
做什么

  • 如果它将执行返回到
    test
    ,那么测试将阻塞
    join
    ,直到线程完成

  • 如果它抛出异常,则不会调用
    join
    ,如果线程尚未结束,则将在
    th
    的析构函数处调用
    std::terminate
    。这可以通过
    try catch

  • 如果强制退出(例如调用
    std::terminate
    ),则。。。好。。。你的节目无论如何都会结束

这确实是一个你需要分析的问题。这完全取决于如果在等待间隔内
terminate
未能停止
execute
,您想做什么

  • 如果您可以在
    test
    中等待,那么您需要做的就是确保调用了
    join
    。正如我所说的,这可以通过
    尝试catch
    来解决

  • 如果您想结束当前测试,但线程仍在运行,则需要在
    终止
    失败时分离线程

  • 如果你想杀死线程,那么。。。那是不可能的。您可以通过
    std::terminate
    杀死整个应用程序


首先,
正在运行
未同步。我不确定,但看起来您也没有运行线程。p.execute();继续执行线程。阅读这篇关于std::thread::detach和std::terminate@Boka的文章时,我感觉构造函数并没有运行线程。我错了。如果terminate()无法停止执行,那么在这个测试用例结束后,这个线程会继续执行吗?@Boka yeah。。。多线程,尤其是低级别的多线程远远不简单。。。