【问题标题】:Is it a good practice to ran a thread from a unit test case?从单元测试用例运行线程是一种好习惯吗?
【发布时间】:2018-10-27 03:38:07
【问题描述】:

我有一个具有 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 没有同步。我不确定,但看起来你也没有运行线程。
  • p.execute();继续执行线程。
  • 阅读有关 std::thread::detach 和 std::terminate stackoverflow.com/questions/22803600/…
  • @Boka 我的印象是构造函数也不运行线程。我错了。

标签: c++ unit-testing visual-c++ mstest


【解决方案1】:

首先应该同步对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 杀死整个应用程序。

【讨论】:

  • 如果 terminate() 未能停止执行,这个测试用例结束后线程会继续执行吗?
  • @Boka 是的...多线程,尤其是低级多线程远非简单...
猜你喜欢
  • 2012-03-01
  • 2017-03-09
  • 2011-01-06
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 2015-05-06
  • 2010-11-25
  • 1970-01-01
相关资源
最近更新 更多