我正在尝试编写自己的moduleUnitTester,它将执行模块中的所有测试,即使一个失败也是如此 . 默认单位测试程序的工作方式如this:
size_t failed = 0;
foreach (m; ModuleInfo) {
if (m) {
auto fp = m.unitTest;
if (fp) {
try {
fp();
}
catch (Throwable e) {
writeln(e);
failed++;
}
}
}
}
fp()抛出第一次失败 . 我真的不喜欢这样,m.unitTest返回void函数,这是一个将执行模块中所有单元测试的函数 . 有没有办法列出这些单元测试并迭代每个单元测试?这不起作用:
foreach (m; ModuleInfo)
{
__traits(getUnitTests, m);
}
这将让我 grab 所有的单元测试,然后自由地迭代它们 . 说'm'是变量而不是模块 . 我找不到任何文件什么是'ModuleInfo'实际上我发现这只是错误的...
2 回答
好吧,既然我在评论中写了一半答案,我想我也可以在这里写一点 .
有一个很好的工作,让您可以访问所有模块 . 您可以尝试遍历导入图,但此方法无法使用本地导入 . 您可以使用构建工具列出您的模块,但这当然要求您实际使用具有该功能的构建工具(https://github.com/atilaneves/unit-threaded是一个使用dub执行此操作的库) .
您也可以将模块的手动列表传递给测试运行器,这是最大的维护工作,但可能具有很好的灵活性 .
但是,我想在运行时这样做,就像你在问题中一样,只是更详细 . 怎么样?通过做一些低级指针的东西!它有时仍然需要成为一个旧的汇编语言黑客:)
看看带有内联注释的代码:
如果需要,我将把调试符号拉出来打印后续测试的文件行信息,作为读者的练习 .
我提供这个肮脏的黑客,希望它有用,但没有任何形式的保证,甚至不适用于特定目的的适销性或适用性 .
我在Linux上使用dmd进行了测试,它可能会或可能不会在其他地方运行,我不知道gdc和ldc是否生成相同的函数,或者它们的优化是否会产生影响等等 .
如果你真的想要一个新的测试运行器,我建议使用支持的技术,如构建工具或手动维护的模块列表与编译时反射相结合:单元线程库除此之外还做了很多漂亮的事情,所以请查看它 .
但是,仅运行时选项也不是一个死胡同:)
我说我发布了我提出的最简单的解决方案..好吧,不幸的是我无法通过我的解决方案实现我想要的,所以毕竟我去了unit-threaded . 我想要做的方法是:使用配音你可以对你的代码进行双重传递,如下所示:
这将导致'dub test'它将首先执行目标gen_ut_main并将Version设置为GenUtMain . 你可以这样做:
然后,generate_file可以生成一个新的“.d”文件,该文件将包含有关所有模块的信息 . 您可以使用'ModuleInfo'来实现它,因为ModuleInfo可以很好地在generate_file函数中使用运行时对象,或者作为单元线程执行此操作,您可以简单地遍历项目中的文件结构并获取所有.d文件,然后您有包列表 . ModuleInfo有1个警告,它会给你所有模块的列表,这可能不是你想要的,因为标准模块将嵌入单元测试,所以你不得不过滤掉这些,我不是能够过滤掉这些,我决定使用单元线程方法 .
现在,在完成目标gen_ut_main之后,将重新生成bin / generated_ut_main.d,它将由unittest目标编译 . 通过这种方式,您可以按模块运行所有单元测试,自由检查UDA并能够在模块中运行所有单元测试,即使一个失败也是如此 .
据说有一个'测试'包与dub集成 . 经过测试可以让您列出所有模块,我无法使其正常工作 .