c++ - 从单元测试用例运行线程是一个好习惯吗?

标签 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()... }

}

下面给出了我的单元测试用例。我正在使用 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>并完成它。

免责声明:我已经有一段时间没有做过任何类型的严肃多线程处理了,所以对此持保留态度。另外,除了检查它的编译情况之外,我还没有测试过代码。

这就是我要开始的地方:

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 是什么。确实如此。

  • 如果它将执行返回到 test那么测试将在 join 上阻塞直到线程结束

  • 如果它抛出异常,则 join没有被调用并且在 th 的析构函数中如果线程仍未结束 std::terminate将被调用。这可以通过 try catch 进行更改

  • 如果它强制退出(例如调用 std::terminate )那么......好吧......你的程序无论如何都会结束

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

  • 如果您可以在test内等待,那么您需要做的就是确保 join叫做。正如我所说,这可以通过 try catch 来解决.

  • 如果您想结束当前测试,但同意线程仍在继续,那么您需要分离线程,如果 terminate未能结束。

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

关于c++ - 从单元测试用例运行线程是一个好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53018505/

相关文章:

unit-testing - 无法使用 i686-linux-android 目标运行单元测试

unit-testing - 开始 TDD - 挑战?解决方案?推荐?

unit-testing - PHPUnit 不加载某些测试

visual-studio-2008 - 使用 Visual Studio 2008 进行 Prefast

C++ 数据结构类似于具有多个键级别的 std::map

c++ - for 循环中的未定义行为 - 表达式分隔不应该使它定义明确吗?

c++ - protocol buffers + zlib = 未解析的外部符号

c++ - 在 chrome native 客户端中运行 C++ Windows 窗体

c++ - GMOCK Clang 讨厌的错误 "/usr/include/limits.h:123:16: fatal error: ' limits.h' 找不到文件”

c++ - 带字符串检查的哈希表