【问题标题】:How to prepare message before Assertion?断言前如何准备消息?
【发布时间】:2021-09-25 18:59:36
【问题描述】:

我是测试新手,刚开始使用“CppUnitTest.h”(Visual Studio2019)。断言静态函数表现良好,例如:

static void Assert::IsTrue(
    bool condition,
    const wchar_t* message = NULL,
    const __LineInfo* pLineInfo = NULL)

但我发现当这样的函数最终发现错误时 - 它会立即破坏程序(在我的案例测试中),并且只做一件事 - 显示消息,我应该在 before 这样指定断言执行。

在测试中,使用循环,我可以在每次迭代时准备完整的消息,但最终运行完整测试需要 6-8 倍的时间。所以这里的理智意图是在它中断之前只为断言指定一次复杂的消息。

感觉应该有办法,但我自己在网上找不到。

我的例子: 整个测试(顺便说一句,知道为什么 UnitTest1 在测试窗口中嵌套 3 次吗?): 附言测试窗口上的最后一个断言仅显示“iter”wchar,根本没有使用“msg”。 主要:

bool applicableAge(UINT age)
{
    if((age>=18 && age<= 50)|| age==1000111222) return true;
    else return false;
};

更新@churill

我认为没有必要粘贴我对“Hello World”级别的简单测试。试想一下,您有一个采用简单 uint 的函数,而我的测试想要测试每个可能的输入(超过 40 亿),现在想象我在目标函数中放置(故意)错误,假设如果输入是 uint,它会产生错误返回1000111222,现在,在我的测试循环中,我必须在每次迭代中编写消息,这需要 至少 3 个操作:1)使用初始消息初始化 wchar_t,2)_itow(i,num,10 ); - 将当前迭代数字转换为文字,3)wcscat(msg, num); - 将必要的文本部分合并到单个 wchar_t 中,直到现在我才能将其作为参数放入 Assert。

现在想象一下,我正在做类似 3x for 的嵌套循环,它需要将 3 个不同的“i”转换为文本,然后将所有这些合并到单个 msg 中。然后很明显,80% 的测试功能是编写实际消息,20% 是对生产代码功能的实际测试。

而我这个问题的目的,是想知道有经验的聪明人会做什么样的伎俩。

我坚信,这应该类似于“Assert::isAboutToBreak()”函数(假设),因此程序员只能合并一次消息,如果您考虑一下,这是有道理的,可以执行断言(失败)只有一次在程序中,当我花费这么多程序资源来'preCombine'消息每次时,我有点傻。

【问题讨论】:

  • 6 到 8 倍?您在测试什么以及如何编写消息?请出示minimal reproducible example 或至少一个您的测试用例。如果看不到您的代码,我们将无法提供有用的答案。
  • @churil 不难看出,收集信息以使断言消息发挥最大作用的过程可能非常耗时。答案不是“让撰写邮件的速度更快”。
  • 如果你使用循环,也许你可以重用部分消息std::wstring message = L"Value should be x but is "; const messageSize = message.size(); for (int i = 0; i &lt; 10000; ++i) { auto const valueExpected = ExpectedValue(i); message += std::to_string(valueExpected); Assert::IsTrue(..., message.c_str()); message.erase(messageSize); };或者,您也许可以编写一个仅在需要时才生成消息的模板。
  • Just imagine that you have function 代码会说 1000 个单词。请只发布代码,而不是从字面上解释代码内容。
  • @fabian 这就是重点,我无法预测何时需要它。

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


【解决方案1】:

首先:您的代码具有未定义的行为。数组不会自动增长,因此wcscat(msg, iter) 将始终写入越界,_itow(i, iter, 10) 将始终写入i &gt; 99。我会选择std::wstring 和/或std::wstringstream


但很明显,与编写错误消息的时间相比,您正在测试的代码几乎不需要时间。

您可以手动断言条件(不带Assert::IsTrueAssert::IsFalse),并且仅在它失败时编写错误消息并使用Assert::Fail 发布。

粗略的例子:

auto expected = calculateExpectedValue();
auto actual = functionYouWantToTest();

if(expected != actual) {
    std::wstring message = composeMessage();
    Assert::Fail(message.c_str());
}

【讨论】:

  • 谢谢@churill。正如我上面所说,在为每次迭代撰写该消息时我感觉有点傻))只有当我现在阅读您的答案时,我才注意到我可以代替直接断言,只需制作消息并打破循环大声笑。作为一个借口,我会说我度过了非常艰难的一周,所以我的大脑变得模糊和疲倦。这么多文本的简单解决方案。请从人类历史中删除这篇文章。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
相关资源
最近更新 更多