Qt应用程序的代码覆盖率
在本教程中,我们将以Qt的TextEdit示例来说明Coco如何在开发过程的不同阶段使用。为了覆盖整个编码周期,我们首先将展示如何创建一个检测过的应用程序,执行手动测试并分析它们的结果。然后我们将创建一个检测过的单元测试。
在第二步(参见使用代码覆盖率数据),我们将介绍对产品经理来说更有趣的方面:分析代码更改的影响(例如,错误修复)——特别是跟踪它们的测试进度、外部化测试和收集完整测试团队的代码覆盖率分析。
示例位置
示例位于名为textedit
的目录中。其位置因操作系统而异。在Microsoft® Windows下,目录直接存储在安装目录中。在Linux™下,可以在/opt/SquishCoco/samples
下找到,而在macOS中则在/Applications/SquishCoco/samples
下。
如果示例具有写保护,则需要创建textedit
目录的副本以进行工作。
编译示例应用程序
在本节中,我们将处理textedit/textedit_v1
目录中的文件。
我们希望能够在不修改源代码的情况下,正常构建和生成测试覆盖率仪表化代码。这可以通过对应用程序的项目文件(.pro
)进行微小修改来实现。然后,我们可以使用qmake
的命令行选项来生成仪表化构建而不是正常构建。
为了使项目文件既适用于正常构建也适用于仪表化构建,我们创建了一组定义,可以通过命令行开关激活;在qmake
的术语中,这被称为一个作用域。以下列表显示了代码仪表化的最小作用域。
以下必须执行的操作
- 必须在代码仪表化时禁用预编译头。通过将
PRECOMPILED_HEADER
变量设置为空值,qmake
允许我们这样做。 - 为了禁用链接脚本的使用,需要增加
QMAKE_LINK_OBJECT_MAX
的值。我们将其设置为10000。 - 最后,必须指示
qmake
使用CoverageScanner的包装器进行编译。这是通过在编译工具名称前添加cs
来完成的。
CodeCoverage { PRECOMPILED_HEADER= QMAKE_LINK_OBJECT_MAX=10000 QMAKE_CC=cs$$QMAKE_CC QMAKE_CXX=cs$$QMAKE_CXX QMAKE_LINK=cs$$QMAKE_LINK QMAKE_LINK_SHLIB=cs$$QMAKE_LINK_SHLIB QMAKE_AR=cs$$QMAKE_AR QMAKE_LIB=cs$$QMAKE_LIB }
这些修改对于大多数标准C和C++应用程序就足够了。对于Qt应用程序,我们必须使用额外的设置以确保CoverageScanner不会仪表化由Qt工具生成的源代码(例如,通过uic
、qrc
和元对象编译器(moc)产生的)。
要排除qrc
资源文件进行仪表化,我们必须通知CoverageScanner不要仪表化任何以qrc_
开头的文件。这可以通过命令行选项--cs-exclude-file-abs-wildcard
=*/qrc_*
来完成。由于我们不想手动输入这个选项,我们将把它放在.pro
文件中。同样,为了让CoverageScanner忽略uic
生成的文件,我们可以使用相同的命令行选项,但这次用不同的文件匹配正则表达式:--cs-exclude-file-abs-wildcard
=*/ui_*
。
Coco默认支持用Qt 4(或Qt 5和Qt 6)工具包构建的应用程序。这样可以确保CoverageScanner
- 不会仪表化
Q_OBJECT
和Q_DECLARE_PLUGIN
宏 - 不会仪表化由
moc
生成的代码(除了信号发射和槽接收是仪表化,因为这对于Qt程序逻辑至关重要)。
注意:如果需要,可以通过选项--cs-no-qt4
禁用此行为。
我们还可以对仪表化的级别和报告的信息进行一些控制。例如,我们可以使用--cs-count
命令行选项开启代码执行的计数,或者使用--cs-full-instrumentation
选项在决策/条件级别启用完全仪表化。使用--cs-output
选项,我们可以在应用程序终止时指定执行报告写入的文件。默认情况下,输出会写入到文件<appname>.csexe
,其中<appname>是已执行的程序名称。)
因此,对于基于Qt的应用程序,应用.pro
文件中的最终Coco作用域将类似于以下内容:
CodeCoverage { COVERAGE_OPTIONS = --cs-output=textedit.exe COVERAGE_OPTIONS += --cs-exclude-file-abs-wildcard=*/qrc_* QMAKE_CFLAGS += $$COVERAGE_OPTIONS QMAKE_CXXFLAGS += $$COVERAGE_OPTIONS QMAKE_LFLAGS += $$COVERAGE_OPTIONS QMAKE_CC=cs$$QMAKE_CC QMAKE_CXX=cs$$QMAKE_CXX QMAKE_LINK=cs$$QMAKE_LINK QMAKE_LINK_SHLIB=cs$$QMAKE_LINK_SHLIB QMAKE_AR=cs$$QMAKE_AR QMAKE_LIB=cs$$QMAKE_LIB }
以这种形式,作用域已被添加到项目文件textedit_v1/textedit_v1.pro
中。当我们现在不带选项运行qmake
时,将生成一个正常构建的Makefile
;但我们还可以以下方式构建程序的仪表化版本
- Linux™ 和 macOS
$ ~/Qt/5.5/gcc/bin/qmake CONFIG+=CodeCoverage $ make
到 qmake 程序的路径当然会根据您使用的 Qt 版本而有所不同。
- 在 Microsoft® Windows 下,还需要设置使
nmake
命令可访问的路径。所有 Microsoft® Visual Studio® 版本都提供了一个 Native Tools Command Prompt 窗口,该窗口为特定编译器版本设置路径。在这样的命令窗口中,编译示例的命令序列可能看起来像这样C:\textedit\textedit_v1>C:\Qt\5.5\msvc2015\bin\qmake CONFIG+=CodeCoverage C:\textedit\textedit_v1>nmake
在两种情况下,我们最终都会得到一个 textedit.exe
可执行文件。但通过经过测量的构建,我们还将得到一个额外的文件,textedit.exe.csmes
。它包含测量数据库。
第一次代码覆盖率结果
在我们的第一个练习中,我们将执行 TextEdit 并立即退出应用程序。这将生成一个名为 textedit.exe.csexe
的执行报告。该文件包含我们刚才执行的最新的执行快照。
要查看结果,必须运行 CoverageBrowser 工具并加载 textedit.exe.csmes
测量数据库。这可以通过菜单项 文件 > 打开 完成。文件打开后,因为没有导入执行报告,所以没有覆盖率信息可用。经过测量的代码行以灰色显示,并且没有计算覆盖率统计信息。
CoverageBrowser 加载 TextEdit 的测量数据库后
为了查看执行报告,请点击 文件 > 加载执行报告,这将调用导入对话框。您需要在字段 文件 > 名称 中输入至少 textedit.exe.csexe
文件的文件名(包括完整路径)。您还需要给出测试一个名字。字段 名称 中输入,例如文本 开始并退出。启用 加载后删除执行报告 选项,因为执行报告在我们导入后不再需要。选择 文件被修改时自动打开此对话框 也是很有帮助的,因为此时每次运行后都会自动打开文件导入对话框。它在测试中创建的新 .csexe
文件然后可以添加到数据库中。
导入完成后,代码覆盖率信息可见
- 显示了应用程序所有源文件中函数和方法的覆盖率统计信息。
- 现在源窗口已着色。它显示在绿色背景上执行的代码和红色背景上未执行的代码。
- 执行列表现在包含一个称为 开始并退出 的选中项,这是我们迄今为止创建的唯一测试执行报告。
交互式测试
CoverageBrowser 透露,例如,TextEdit::fileSave()
函数未执行。现在我们将通过代码覆盖率分析交互式验证此函数。
在源窗口中,所有未执行的源代码行都显示在红色背景上。
bool TextEdit::fileSave() { if (fileName.isEmpty()) { QMessageBox::warning(this, tr("No file name specified"), tr("Save first your document using 'Save As...' from the menu"), QMessageBox::Ok); return false; } QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); if (success) textEdit->document()->setModified(false); return success; }
要测试此函数,必须执行以下步骤
- 启动 TextEdit 应用程序。
- 点击 保存 按钮: TextEdit 应该显示错误消息 请使用 '另存为' 从菜单中保存文档。
- 退出应用程序。
完成这些步骤并导入执行报告后,CoverageBrowser 显示 return false;
行在调用 QMessageBox::warning()
后已执行,如绿色背景所示。但是 if (fileName.isEmpty())
行只部分执行:这通过橙色背景表示。
bool TextEdit::fileSave() { if (fileName.isEmpty()) { QMessageBox::warning(this, tr("No file name specified"), tr("Save first your document using 'Save As...' from the menu"), QMessageBox::Ok); return false; } QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); if (success) textEdit->document()->setModified(false); return success; }
解释窗口显示,表达式 fileName.isEmpty()
在一次执行中为 true,但从未为 false。因此,它被认为只是部分执行。为了完全测试此表达式,我们必须点击 保存为 按钮,然后选择文件名,最后点击 保存 按钮。
部分执行: fileName.isEmpty()
TRUE | FALSE |
---|---|
是 执行次数: 1 执行者: - 点击保存 | 否 执行次数 0 |
重新运行应用程序并在执行 保存为 之后,新的执行报告只有一个部分未测试的源代码行。在这种情况下,CoverageBrowser 显示布尔变量 success
从未为 false,这意味着保存文档从未失败。
我们可以强制写入失败,这将确保我们对此函数有 100% 的代码覆盖率。但我们将使用不同的测试策略来获取完整的代码覆盖率:我们将使用单元测试并将执行结果导入到 TextEdit 的仪器数据库。
bool TextEdit::fileSave() { if (fileName.isEmpty()) { QMessageBox::warning(this,tr("No file name specified"), tr("Save first your document using 'Save As...' from the menu"), QMessageBox::Ok ); return false; } QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); if (success) textEdit->document()->setModified(false); return success; }
编写单元测试
单元测试基础设施可以在目录 textedit_v1_tests/
中找到。它只包含一个测试,该测试设置了一个非法的文件名,然后尝试执行 TextEdit 的 fileSave()
函数。为此,我们使用 Qt 部分的功能性库 Qt Test
单元测试库。测试包含在文件 textedit_v1_tests/tst_textedit.cpp
中。
#include "tst_textedit.h" void TestTextEdit::tst_saveFile() { TextEdit textEdit; textEdit.fileName="/"; QVERIFY( !textEdit.fileSave() ); } QTEST_MAIN(TestTextEdit);
要将此测试的仪器结果导入到 TextEdit 的仪器数据库中,需要以下基础设施
- 一个与 TextEdit 项目的配置相同的带有代码覆盖率的
qmake
项目文件。 - 一个后构建规则,它自动执行测试并收集覆盖率信息。
- 一个单元测试监听器,它将每个执行的测试的代码覆盖率数据(以及测试状态——通过或失败)保存到单元测试的仪器数据库中。
- 将代码覆盖率报告导入到 TextEdit 的仪器数据库的方法。
单元测试将与 textedit_v1/textedit.cpp
一起重新编译。为了使结果显示可导入到 TextEdit 的仪器数据库中,这两个可执行文件(TextEdit 和单元测试)都必须以 正好 相同的方式进行仪器设置。由于我们只使用默认的仪器,因此这一要求已经得到满足。
不幸的是,这还不是我们需要的全部东西。Coco 的默认行为是仅对其被调用的目录中的头文件和源文件进行仪器设置,但在这里我们还需要对 TextEdit 应用程序的源文件进行仪器设置。因此,我们必须使用另一个命令行选项来指定要仪器化的文件的额外路径:--cs-include-path
。
与之前一样,我们不希望每次都记住这些命令行参数,所以我们在 qmake
项目文件中设置它们, textedit_v1_tests.pro
。在这些单元测试项目文件中的行,qmake
生成的 Makefile
将创建 tst_textedit.exe
可执行文件,当运行时,会生成执行报告 tst_textedit.exe.csexe
。然后我们可以使用 CoverageBrowser 将该报告导入到文件 tst_textedit.exe.csmes
中。
HEADERS = ../textedit_v1/textedit.h tst_textedit.h SOURCES = ../textedit_v1/textedit.cpp tst_textedit.cpp CodeCoverage { COVERAGE_OPTIONS = --cs-output=tst_textedit.exe COVERAGE_OPTIONS += --cs-include-path=../textedit_v1 COVERAGE_OPTIONS += --cs-exclude-file-abs-wildcard=*/qrc_* QMAKE_CXXFLAGS += $$COVERAGE_OPTIONS QMAKE_CCFLAGS += $$COVERAGE_OPTIONS QMAKE_LFLAGS += $$COVERAGE_OPTIONS QMAKE_CC=cs$$QMAKE_CC QMAKE_LINK=cs$$QMAKE_LINK QMAKE_CXX=cs$$QMAKE_CXX }
我们还可以通过后构建规则自动执行单元测试并将执行报告导入。Coco 提供了一个额外的命令行工具 cmcsexeimport(见 cmcsexeimport – 命令行导入实用程序),该工具将执行报告导入到仪器数据库中。后构建规则首先删除任何以前的执行报告,然后执行测试本身,最后将结果导入到应用程序的执行数据库,tst_textedit.exe.csexe
。
CodeCoverage { win32: MAINDIR=$$replace(PWD,"/","\\") !win32:MAINDIR=$$PWD unix { QMAKE_POST_LINK = rm $$MAINDIR/tst_textedit_v1.exe.csexe ; QMAKE_POST_LINK += $$MAINDIR/tst_textedit_v1.exe ; QMAKE_POST_LINK += cmcsexeimport -m $$MAINDIR/tst_textedit_v1.exe.csmes \ -e $$MAINDIR/tst_textedit_v1.exe.csexe -t UnitTest } win32 { QMAKE_POST_LINK = del /F $$MAINDIR\\tst_textedit_v1.csexe & QMAKE_POST_LINK += $$MAINDIR\\tst_textedit_v1.exe & QMAKE_POST_LINK += cmcsexeimport -m $$MAINDIR\\tst_textedit_v1.exe.csmes \ -e $$MAINDIR\\tst_textedit_v1.csexe -t UnitTest } }
默认情况下,覆盖率数据导入时不包含关于执行测试的任何信息。相反,创建了一个名为UnitTest
的执行报告,它不描述哪项测试被执行或其执行是否成功。为了提供缺失的信息,必须使用CoverageScanner API并为每个执行的测试生成一个执行报告。如何执行此操作的示例可见于Qt Test。在示例中,API的使用方式如下:
- 向
qmake
项目文件中添加了两个Coco源文件。HEADERS += testcoverageobject.h SOURCES += testcoverageobject.cpp
- 单元测试类
TestTextEdit
继承自TestCoverageObject
,而不是直接继承自QObject
。#include "testcoverageobject.h" #include "../textedit_v1/textedit.h" #include <QtTest/QtTest> class TestTextEdit : public TestCoverageObject { Q_OBJECT private slots: void tst_saveFile(); };
testcoverageobject.cpp
文件的源代码向Qt Test
添加了单个cleanup()
函数,该函数在每个单元测试项之后执行。仅在调用CoverageScanner时,#ifdef __COVERAGESCANNER__
和#endif
之间的代码才会编译。这段额外的代码通过组合测试类的对象名和测试函数名来创建一个测试名称。在示例中,生成了一个名为unittest/TestTextEdit/tst_saveFile
的执行项。斜线用于支持在树形视图中组织测试。通过__coveragescanner_save()
函数记录并添加到执行报告中的当前测试状态(PASSED或FAILED)。
... void TestCoverageObject::cleanup() { cleanupTest(); #ifdef __COVERAGESCANNER__ QString test_name="unittest/"; test_name += metaObject()->className(); test_name += "/"; test_name += QTest::currentTestFunction(); __coveragescanner_testname(test_name.toLatin1()); if (QTest::currentTestFailed()) __coveragescanner_teststate("FAILED"); else __coveragescanner_teststate("PASSED") ; __coveragescanner_save(); #endif }
注意:符号__COVERAGESCANNER__
由CoverageScanner自动定义,因此不需要手动定义。
到此阶段,我们可以启动CoverageBrowser,通过点击文件 > 导入单元测试来加载TextEdit
的仪器化数据库,并导入单元测试的仪器化数据库。一个更方便的替代方案是使用cmmerge工具来自动执行此步骤。该cmmerge程序的设计是为了将一个仪器化数据库的执行报告导入另一个仪器化数据库。这意味着我们可以将我们的构建后规则扩展到使用cmmerge程序,从单元测试自动导入覆盖率信息到TextEdit程序的仪器化数据库。
CodeCoverage { # Merge coverage database into TextEdit database unix { QMAKE_POST_LINK += ; QMAKE_POST_LINK += cmmerge -o $$MAINDIR/../textedit_v1/textedit.tmp \ -i $$MAINDIR/../textedit_v1/textedit.exe.csmes \ $$MAINDIR/./tst_textedit_v1.exe.csmes && QMAKE_POST_LINK += rm $$MAINDIR/../textedit_v1/textedit.exe.csmes && QMAKE_POST_LINK += mv $$MAINDIR/../textedit_v1/textedit.tmp \ $$MAINDIR/../textedit_v1/textedit.exe.csmes } win32 { QMAKE_POST_LINK += & QMAKE_POST_LINK += echo Merging unit test result into the main application & QMAKE_POST_LINK += cmmerge -o $$MAINDIR\\..\\textedit_v1\\textedit_unit.exe.csmes \ -i $$MAINDIR\\..\\textedit_v1\\textedit.exe.csmes \ $$MAINDIR\\tst_textedit_v1.exe.csmes & QMAKE_POST_LINK += COPY /Y $$MAINDIR\\..\\textedit_v1\\textedit_unit.exe.csmes \ $$MAINDIR\\..\\textedit_v1\\textedit.exe.csmes & QMAKE_POST_LINK += DEL /F $$MAINDIR\\..\\textedit_v1\\textedit_unit.exe.csmes } }
在.pro
文件中实施所有这些更改后,我们再次构建并运行单元测试。现在,CoverageBrowser显示了覆盖率100%的fileSave()
函数,执行列表包含我们的三个原始手动测试和一个单元测试。
所有测试执行完成后的执行列表
与代码覆盖率数据协作
开发者使用代码覆盖率数据最常见的方式是找到未测试的代码,以及经理生成测试状况报告(例如,作为图表)。
除了全面支持常用用例之外,Coco还提供了额外的功能,使得超越这些基础使用成为可能,并扩展可以用代码覆盖率达到的成果。这将在当前子部分中讨论。
事后分析
记录每个测试的覆盖率数据使得我们可以将这些数据与它们进行比较,以回答这个问题:“这个测试覆盖了除其他之外的内容是什么?”这特别有用,如果只有一个测试失败,因为它可以帮助我们确定涉及代码的哪个部分。
为了了解这种方法在实际中的运用,让我们回到TextEdit
的示例。如果我们点击保存,我们将得到一个错误消息,说明没有定义文件名。这对用户来说不太方便——我们应该设计TextEdit来通过打开另存为对话框来处理这个特殊情况,而不是产生错误。
为了确定代码中这个问题出现在哪里,我们简单地比较Save Clicked的执行与其他涉及Save按钮的所有执行。要这样做,首先需要通过选择Tools > Execution Comparison Analysis切换到Execution Comparison Analysis模式。为tst_saveFile和SaveAs clicked before Save clicked测试选择Reference列中的复选框。这将使执行比较符号出现在受影响名称之前。在Executions列中,点击Save clicked复选框。
正在使用的执行列表以比较不同的执行
在此模式下,覆盖率分析仅基于tst_saveFile和SaveAs clicked before Save clicked未执行的源代码行。这就是整体覆盖率降至1.29%的原因:这意味着《Save clicked》执行比所选测试多0.29%的代码。
使用cmreport生成HTML报告,它显示相同的信息
cmreport --csmes=textedit_v1/textedit.exe.csmes \ --html=textedit.html \ --section=execution \ --select-reference=".*tst_saveFile" \ --select-reference="SaveAs clicked before Save clicked"
如果我们现在查看源代码本身,则会看到只有TextEdit::fileSave()函数的两行没有灰色显示:弹出错误消息的行。必须修改这些行以更改Save按钮的行为。
bool TextEdit::fileSave() { if (fileName.isEmpty()) { QMessageBox::warning(this,tr("No file name specified"), tr("Save first your document using 'Save As...' from the menu"), QMessageBox::Ok ); return false; } QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); if (success) textEdit->document()->setModified(false); return success; }
在这种情况下,更改fileSave()函数很容易——我们只需将QMessageBox::warning()调用替换为对fileSaveAs()方法的调用。
bool TextEdit::fileSave() { if (fileName.isEmpty()) return fileSaveAs(); QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); if (success) textEdit->document()->setModified(false); return success; }
评估热补丁的影响
在提交更改或开始测试热补丁之前,可以估计代码修改的影响。CoverageBrowser能够对两个源集之间的差异进行分析,并可以列出受影响的测试(以及不受影响的测试)。
启动CoverageBrowser并加载修改后的TextEdit示例的仪器化数据库。现在点击Tools > Compare with并选择原始版本的TextEdit仪器化数据库。CoverageBrowser现在会像文本比较应用程序那样显示源代码(例如,diff
)。
点击Tools > Analysis of Modified Functions以排除所有未修改的函数的覆盖率分析。在TextEdit的情况下,这样做意味着只有一个函数TextEdit::fileSave()会被视为仪器化的,因为我们只更改了此方法。这也影响了统计计算,因为执行覆盖率统计现在将仅限于这个函数。覆盖率统计不为零的测试执行是我们已进行的代码更改所影响的。
在我们的情况下我们有
- Save clicked
- SaveAs clicked before Save clicked
- tst_saveFile(我们的单元测试)
Start and Exit情况覆盖率为0%,因此没有执行我们的修改代码。因此,它不再出现在执行列表中。执行列中的所有条目都划掉了,以此通知我们这些测试在最新版本中未执行,仅在参考数据库中存在。
换句话说,只有上述列出的两个手动测试和单元测试必须重新执行,以确保我们没有通过代码更改引入回归。
代码修改影响的测试列表
黑盒测试/分布式测试
截至目前,我们已经进行了白盒测试,即可以访问源代码并利用对代码的了解进行的测试。也可以使用 Coco 进行黑盒测试。换句话说,我们可以仍然在不访问甚至不知道源代码的情况下进行代码覆盖率分析。如果我们使用这种方法,生成的仪器数据库当然不包含源代码。
要使用黑盒测试,必须通过点击 文件 > 生成黑盒配置 创建合适的仪器数据库。这个数据库,连同 TextEdit 可执行文件,可以提供给测试团队,然后他们可以使用简化版的 CoverageBrowser。这个版本的 CoverageBrowser 只支持导入和管理执行报告,因为它无法访问应用程序的源代码。
由 CoverageBrowser 显示的黑盒测试结果
所有测试完成后,可以使用 CoverageBrowser 的合并功能(文件 > 与... 合并)将黑盒数据库合并到原始的 TextEdit 仪器数据库中。
验证bug修复是否经过正确测试
通常,当修复一个小错误时,其影响局限于较小范围,且大部分源代码保持不变。考虑到这一点,通常没有必要使用整个测试套件重新测试整个应用程序。
Coco 可以使我们避免不必要的测试。我们可以指示它仅限于应用程序原始版与修复版之间发生变化的源代码(参见评估热修复的影响)。这允许我们纯粹关注修复的分析。为了实现这一点,只需加载修复应用程序的新生成仪器数据库(例如,为修改后的 TextEdit 应用程序),并将其与较早期未修复版本的早期数据库进行比较,使用 Coco 的修改函数分析功能。
修复函数的覆盖率
我们已经进行了这样的比较,结果如上图所示。这两个测试,点击保存 和 开始和退出,覆盖了 85% 的 TextEdit::fileSave()
函数,这是我们修复中唯一修改的方法。从这一点我们可以确切知道为了实现应用修复版本的 100% 代码覆盖率还需要进行哪些额外的测试。CoverageBrowser 继续以删除线风格显示缺少的测试列表(这些测试仅使用 TextEdit 的第一个版本执行),这提供了一个关于剩余测试工作量的提示。
使用cmreport生成HTML报告,它显示相同的信息
cmreport --csmes=textedit_v2/textedit.exe.csmes \ --csmes-reference=textedit_v1/textedit.exe.csmes \ --html=textedit.html \ --section=execution
结论
Coco 提供了代码覆盖率分析,可以应用于所有常见的测试技术:单元测试、手动测试和黑盒测试。Coco 可以轻松地被指示忽略 Qt 库工具(如 moc
,qrc
和 uic
)生成的生成代码,因此只有开发者编写的代码被仪器化。测试结果可以收集到数据库中,并可用于评估我们的测试实现了多少代码覆盖率以及显示哪些语句尚未被测试。有了这些信息,我们可以有针对性地将测试工作集中在 100% 测试代码覆盖率上。此外,Coco 还允许在不测试整个应用程序的情况下看到代码修改对测试代码覆盖率会产生什么影响。
总的来说,Coco 可以帮助我们确保我们的应用程序具有尽可能多的测试覆盖率,同时避免或最大限度地减少测试覆盖率重复。此外,Coco 还可以帮助我们看到我们的代码更改对测试覆盖率产生的影响,从而使我们能够相应地调整测试套件。
Coco v7.2.0©2024Qt公司有限公司。
Qt 及其相关标志是Qt公司在芬兰及/或其他世界国家的商标。所有其他商标均为其各自所有者的财产。