【问题标题】:Using Assert() in a C++ test project for "test project" bugs?在 C++ 测试项目中使用 Assert() 来解决“测试项目”错误?
【发布时间】:2021-12-02 02:16:31
【问题描述】:

是否适合在 Visual Studio C++ 测试项目中使用 Assert() 函数来解决测试项目中的错误?用于 C++ 的 Visual Studio 测试项目 命名空间 Microsoft::VisualStudio::CppUnitTestFramework

例如,我有一个函数可以构建一个充满随机 char 值字符串的向量,我应该如何处理该类的用户使用错误参数的情况?添加 Assert::IsTrue(myVec.size() > 0) 是否合适,然后测试项目可能会自行导致测试失败?

一个例子:

    /// <summary>
    /// Returns a vector of std::string with randomized content.
    /// count is the number of entries in the returned vector, length is the max length of the strings.
    /// </summary>
    /// <returns> a vector of std::string with randomized content. Empty vector on error. </returns>
    std::vector<std::string> BuildRandomStringVector(const int count, const int length, const int minLength = 3)
    {
        //arg error checking, returns empty vector as per description
        if (minLength >= length || (length <= 0) || (count <=0) || (minLength <=0))
        {
            return std::vector<std::string>();
        }

        //Test all kinds of random character possibilities.
        std::uniform_int_distribution<int> distCharPossibility
        (std::numeric_limits<char>::min(), 
            std::numeric_limits<char>::max());

        std::uniform_int_distribution<int> distLengthPossibility(minLength, length);

        std::random_device rd;
        std::mt19937 stringGenerator(rd());
        std::vector<std::string> ret;

        //the distribution uses the generator engine to get the value
        for (int i = 0; i < count; i++)
        {
            const int tLength = distLengthPossibility(stringGenerator);
            std::string currentBuiltString = "";
            for (int j = 0; j < tLength; j++)
            {
                char currentBuiltChar = distCharPossibility(stringGenerator);
                currentBuiltString += currentBuiltChar;
            }
            ret.push_back(currentBuiltString);
        }

        return ret;
    }

【问题讨论】:

  • 示例中没有Assert
  • 苹果,假装有“Assert::IsTrue(minLength >= length);”等在函数顶部的错误检查中,而不是返回一个空向量。但就此而言,Assert 可以在测试项目中的任何位置,问题是测试项目代码是否应该导致正在测试的项目的测试失败?
  • @woofdiggy 添加Assert没有错,只是语义不同。

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


【解决方案1】:

我不建议在测试中使用任何形式的断言。理由如下。断言是一个诊断代码,通常在“调试”模式下执行并在“发布”中跳过。您不打算以两种不同的模式运行测试,是吗?而且您不会进行测试。验证代码中的条件不应对测试执行时间产生任何可衡量的影响。在这种情况下,更喜欢可靠性:始终执行测试,因为您当然可以承受几微秒长的测试。如果违反条件应被视为错误,请不要返回空向量:您是否每次都在调用者处检查其大小?抛出异常。简而言之,而不是断言,使用std::invalid_argument 或类似的东西。开火即忘。

从另一个角度来看:原则上我们可以在生产代码中嵌入大量自测,但我们更喜欢外部测试,这样生产代码才能真正精简和快速。这个问题对于测试来说并不那么重要:如果你担心它们会被不恰当地使用,那就明确地、无条件地测试它们的使用正确性。使用常识来判断开销何时仍然可以接受。

【讨论】:

  • 在发布模式下可能不会跳过良好的测试框架断言。 (可能它实际上是有例外地实现的)
  • @appleapple 是的。例如,GoogleTest 有 ASSERT_TRUE、ASSERT_EQ 等宏。它们总是被评估,但它们属于框架。我想我会编辑答案。
  • @appleapple 一段时间后,我得出结论,使用测试框架断言不是最好的解决方案。我使用 GTest 中的 ASSERT_TRUE 之类的宏,因为其中测试的条件对于其余测试“正常”是绝对必要的。例如,如果向量为空,则调用其front 成员函数将是错误的。 OP描述的场景如何处理应该由开发者决定,但Assert不属于可接受的解决方案。
  • 不确定区别在哪里? OP 说他正在使用Microsoft::VisualStudio::CppUnitTestFrameworkmention Assert::IsTrue,这应该是一个测试框架断言,与ASSERT_TRUE 相同。它绝对属于可接受的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多