img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

{
    if (input[inputIter] == ' ')

    {
        if (indics[1] == 0)

            indics[1] = -1;

        else if (indics[1] > 0)

            break;

    }

    else if (input[inputIter] != ' ' && indics[1] == -1)

        indics[1] = inputIter;

}

// copy second word, inputIter points to the end of second word

if (indics[1] > 0)

{
    for (int i = indics[1]; i < inputIter; ++i)

        result[resultIter++] = input[i];

    indics[1]--;

    // copy white space

    while (indics[1] >= 0 && input[indics[1]] == ' ')

        indics[1]--;

    result[resultIter++] = ' ';

}

else

    indics[1] = input.Length - 1;

// copy the first word

for (int i = indics[0]; i <= indics[1]; ++i)

    result[resultIter++] = input[i];

// next pair

if (inputIter < input.Length)

{
    result[resultIter++] = ' ';

    ReverseStringPairImp(input, inputIter, result, resultIter);

}

}


创建单元测试用例  
 把鼠标放在ReverseStringPair函数的声明上(或者说第一行),点击右键,并且选择“创建单元测试”命令,一切按照默认的设置选择“确定”按钮,创建一个测试工程。


在新创建的测试工程自动添加的programtest.cs(因为类名叫做program)文件里,添加一个新测试用例:


Programtest.cs



[TestMethod()]

public void ReverseStringPairTest()

{
string input = “ab cd ef gh”;

string expected = "cd ab gh ef";

string actual = Program.ReverseStringPair(input);

Assert.AreEqual(expected, actual);

}


单元测试用例创建好了以后,点击工具栏里面的“Run Tests in Current Context”,就能看到测试结果了,如下图所示:


![](https://img-blog.csdnimg.cn/img_convert/0b03eafb91b6e40450d9da56fbc1d5c7.png)


启用代码覆盖率测试


只执行单元测试是不能检查代码覆盖情况的—即你创建的测试用例总共覆盖了多少行源代码。为什么需要特意开启代码覆盖率测试是有原因的,这个在文章的最后会讲到。


1.       在“解决方案浏览器(Solution Explorer)”里,双击“localtestrun.testrunconfig”文件。


2.       在弹出的“localtestrun.testrunconfig”窗口里,双击“代码覆盖率(Code Coverage)”。


3.       里面会列出好几个文件,有.dll ,也会有.exe。勾选你要测试代码覆盖率的程序,比如说你要测试WildChar工程—也就是我们的产品代码的代码覆盖率,请勾选WildChar.exe。不要勾选包含测试用例的那个dll文件,因为我们对测试代码本身的覆盖率没有任何兴趣。结果如下图所示:  
![](https://img-blog.csdnimg.cn/79cb991a9482487baea3be0c118a758e.png)


4.        点击“应用(Apply)”关闭窗口。


在重新运行一下所有的测试用例,点击测试结果窗口工具栏最右边的按钮,查看代码覆盖率情况,如下图所示:


![](https://img-blog.csdnimg.cn/07b334fd905a49f983d78c00b015c213.png)


 代码覆盖率是按百分比计算的,即 Visual Studio会告诉你,有百分之多少的产品代码被覆盖了,而且你也可以查看单个函数的代码覆盖率,如下图所示:


![](https://img-blog.csdnimg.cn/2fb22e61f2bf41f3bf4ecee77618790e.png)


在“代码覆盖率结果”列表里双击每个函数名,你可以看到具体的代码覆盖信息,青绿色的代码是完全被覆盖到的,红色的代码是从来没有执行过的,而黄色的代码表示这一行有一部分代码被执行过—之所以说有一部分通常是因为一行代码有多个判断条件,有些条件执行了,有些却没有。如下图所示:


![](https://img-blog.csdnimg.cn/328cefc5874240b1a7457d39fbd33f1a.png)


代码覆盖率的实现原理  
 看到这里,是不是有点神奇?为什么执行过一些自动化测试用例,就可以查看代码覆盖率呢?它是怎么实现的呢?


实际上我们在“localtestrun.testrunconfig”窗口里面设置查看代码覆盖率那一步时,Visual Studio悄悄地修改了WildChar.exe,在原来的IL 代码里添加了一些新的语句。


在解释之前,我们先考虑代码覆盖率的意思,代码覆盖率的意思其实就是表明有多少行代码被执行到了,因此首先要统计有多少块代码,然后再统计有多少块代码被执行了。什么叫代码块呢,代码块就是一段连续的代码。例如在program.cs里面,下面这些代码行组成一个代码块:



char[] result = new char[input.Length];

int resultIter = 0;

ReverseStringPairImp(input, 0, result, resultIter);

return new string(result);


因为上面的代码,如果不ReverseStringPairImpl 函数不抛出异常的话,就会连贯地执行下去,因为上面四行代码可以看成是一块代码(或者说是一行代码)。


而下面的代码则可以看成是两块代码



if (indics[1] == 0)

indics[1] = -1;

else if (indics[1] > 0)

break;

要么是第一个if执行,要么第二个if 执行。


下面的代码会有点意思,虽然是一行代码,但是可以当作两个代码块来看待:



while (inputIter < input.Length && input[inputIter] == ’ ')


1.       要么前面一个条件成立,后面的条件不成立,那么最后一个语句不执行;


2.       要么两个条件都成立,最后语句执行;


3.       要么两个条件都不成立,最后一条语句不执行。


由于第二个条件存在不被执行的机会—即我们设计的所有测试用例都导致第一个条件总是不成立,所以这也是为什么在显示代码覆盖率结果的时候,上面那行代码只有部分覆盖到的原因。


有了代码块的概念之后,在实现代码覆盖率这个功能时,我们可以用一个大的布尔数组来保存有多少块代码被执行这个信息,而布尔数组的长度呢,就是程序的代码块的个数(因为一块代码可以看成一行代码)。也就是说,我们可以把产品代码手工修改成类似下面的样子:



bool pathCovered[] = new bool[11]; // 11是统计下来程序里面代码块的个数

for ( int i = 0; i < pathCovered.Length; ++i )

  pathCovered[i] = false;

// while (inputIter < input.Length && input[inputIter] == ’ ') inputIter++;

firstblock:

bool result = inputIter < input.Length;

pathCovered[0] = true;

if ( result )

{
    result = input[inputIter] == ' ';

    pathCovered[1] = true;

}

else

{
    pathCovered[2] = true;

    goto secondblock;

}

if ( result )

{
    pathCovered[3] = true;       

    inputIter++;

    goto firstblock;

}

secondblock:

pathCovered[4] = true;       

int[] indics = new int[2] {
    inputIter, // first word begin index,

    0 // second word begin index

};

for (; pathCovered[5] = true, inputIter < input.Length;

       pathCovered[6] = true, ++inputIter)

{
    pathCovered[7] = true;

    if (input[inputIter] == ' ')

    {
        pathCovered[8] = true;

        if (indics[1] == 0)

        {
            pathCovered[9] = true;

            indics[1] = -1;

        }

        else if (indics[1] > 0)

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

g-s8MexC41-1715141836091)]
[外链图片转存中…(img-3y6Hrk3F-1715141836091)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

Logo

一站式 AI 云服务平台

更多推荐