<VS2017> 编写VC++单元测试 -(一)新建单元测试工程

开发人员自己编写单元测试是一个非常好的习惯。单元测试不但能够验证自己所编写的代码是否存在问题,避免提交给测试人员时才发现bug,也可以为将来改动代码的人提供验证代码功能正确性的途径。在我有限的工作生涯中并未写过太多单元测试,所以我在这方面亦存在诸多不足,所述如果有纰漏,还望各位读者不吝指点。

 

单独的单元测试工程一般是为了测试暴露给外部程序调用的接口,这样可以保证调用者(单元测试程序)和被调用者(接口)的分离。不过有些时候,我们也要给工程的内部关键方法写一些单元测试,这个时候就需要将测试用例写在工程内部。首先我们先来学习一下如何创建一个单元测试工程。

1. 准备工作

我们先创建一个动态链接库工程,并准备好一个导出函数。关于如何创建动态链接库我就不赘述了,我们导出的函数如下:

int getOddCount(int number)
{
    int nCount = 0;

    for (int i = 1; i <= number; i++)
    {
        if (i % 2 != 0)
        {
            nCount++;
        }
    }

    return nCount;
}

这个函数的功能是,给定一个整数,返回1到这个整数范围内的所有奇数的个数。

为了配合单元测试,请保证这个动态链接库工程能够正常生成dll和对应的lib文件,并提供导出函数对应的头文件。

 

2. 创建单元测试工程

在Solution中单击右键,创建新的单元测试工程。这里我们选择Native Unit Test Project.

 

工程名字可以随便写,暂时用默认的就可以。 

工程创建完成够,整个solution的结构应该如下图所示:

其中在unittest1.cpp中是自动生成的单元测试模板。

 

3. 配置单元测试工程

为了能够让单元测试工程和我们创建的动态链接库工程关联上,我们需要做如下配置。

首先,让单元测试工程引用动态链接库工程。

然后再将动态链接库的代码路径加入到单元测试的Include Directories。

 

4. 编写单元测试代码

我们先简单看一下unittest1.cpp这部分代码。

namespace UnitTest1
{        
    TEST_CLASS(UnitTest1)
    {
    public:
        
        TEST_METHOD(TestMethod1)
        {
            // TODO: Your test code here
        }

    };
}

namespace UnitTest1 :

这个命名空间名字可以改,但是建议和文件名一致,这样方便以后看代码

TEST_CLASS(UnitTest1) :

这个宏设定单元测试的类的名称,单元测试的名字也尽量要可读。需要注意的是这是class的名字,需要符合class的命名规范

TEST_METHOD(TestMethod1) :

要测试的方法,名字也可以随便起,但是最好要和要测试的方法保持一致。比如要测试的方法叫做method,那么测试方法就叫TestMethod。

 

在编写测试代码时和正常编码并没有什么不同。单元测试的主要思想是通过给定输入以及预期的输出,来判断方法实现是否有问题。比如要测试一个求和函数,输入为1和2,那么预期输出是3。如果调用方法之后得到的结果不是3,那么这个测试用例就会失败,单元测试结果则为失败。

具体到我们这个测试,参照如下代码,输入参数是10,那么我们应该得到的结果是5,因为1到10之间共有5个奇数。

(注意,不要忘记在unittest1.cpp中include动态链接库的头文件)

TEST_METHOD(TestMethod1)
{
    Assert::AreEqual(getOddCount(10), 5);
}

在单元测试中,需要使用Assert这个类中的方法对结果进行判断,这样测试结果才会正确的反馈到IDE中。上面的代码中用到的是AreEqual方法,用于判断预期结果与方法调用后的结果是否相同。

Assert类中有很多用于测试的方法,除了相等还有不等,真假等等,也有让测试强制失败的方法,可以根据具体的情况是使用。

测试代码写完后,我们编译整个solution或者编译单元测试project,如果编译没有问题的话,就可以开始测试了。

 

5. 运行单元测试

在上一步中,如果没有编译问题的话,我们就可以在Test Explorer中看到现在所有的单元测试。注意,如果更新了单元测试代码,需要对project重新进行编译。通过菜单中的Test->Windows->Test Explorer可以打开Test Explorer。

在Test Explorer中点击Run All就会开始运行所有的单元测试。稍等一会,如果测试通过,就会有如下图显示:

这绿色看着真舒服(?)。那么如果测试未通过呢?

让我们再修改一下我们的代码,让我们的getOddCount函数产生一点小小的错误…

int getOddCount(int number)
{
    int nCount = 0;

    for (int i = 2 i <= number; i++)
    {
        if (i % 2 != 0)
        {
            nCount++;
        }
    }

    return nCount;
}

重新编译整个solution之后,再次重新运行所有的单元测试

啊...多么醒目的红色...

双击失败的单元测试,我们可以快速定位到出错的地方。

 

6. 可能遇到的错误

如果使用的时x64平台,可以会因为单元测试工程和目标工程的平台(x86和x64)不一致导致运行时错误,错误提示如下:

Make sure that test discoverer & executors are registered and platform & framework version settings are appropriate and try again.

这个时候只要通过菜单Test -> Test Settings -> Default Processor Architecture调整单元测试使用的CPU架构即可。

 

到这里,关于使用单元测试工程的基本内容就讲完了,如果想有更深一步的了解,可以参考MSDN官方文档

下一次,我将讲一下如何创建工程内部的单元测试(不使用单独的project)。

转载于:https://www.cnblogs.com/czhao4/p/10021011.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,那么我们可以先针对 `TaskPollRunnable` 类中的 `pollTasks` 方法写一个单元测试。由于该方法的返回值是通过调用 `ftpManagerClient.getCleanTasks(num)` 来获取的,所以我们需要使用 mock 对象来模拟这个调用。 首先,我们需要在 `pom.xml` 中引入 JUnit 和 PowerMock 的依赖: ```xml <dependencies> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- PowerMock --> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> </dependencies> ``` 然后,我们可以编写如下的测试代码: ```java @RunWith(PowerMockRunner.class) @PrepareForTest({FtpManagerClient.class}) public class TaskPollRunnableTest { private CleanTaskPollService cleanTaskPollService; private FtpManagerClient ftpManagerClient; @Before public void setUp() throws Exception { cleanTaskPollService = new CleanTaskPollService(/* 传入参数 */); ftpManagerClient = mock(FtpManagerClient.class); Whitebox.setInternalState(cleanTaskPollService, "ftpManagerClient", ftpManagerClient); } @Test public void testPollTasks() throws Exception { // 构造 mock 返回值 FileCleanTaskResponse response = new FileCleanTaskResponse(); List<FileCleanTask> tasks = new ArrayList<>(); FileCleanTask task1 = new FileCleanTask(); task1.setCleanDirs(Arrays.asList("/path/to/dir1", "/path/to/dir2")); tasks.add(task1); response.setCleanTasks(tasks); // 设置 mock 对象的行为 Response<FileCleanTaskResponse> mockResponse = Response.success(response); Call<FileCleanTaskResponse> mockCall = mock(Call.class); when(ftpManagerClient.getCleanTasks(anyInt())).thenReturn(mockCall); when(mockCall.execute()).thenReturn(mockResponse); // 调用被测试方法 FileCleanTaskResponse result = cleanTaskPollService.pollTasks(1); // 验证结果 assertEquals(response, result); } } ``` 这个测试用例使用了 PowerMock 框架来 mock `FtpManagerClient` 类的实例,并设置其调用 `getCleanTasks` 方法时返回指定的 mock 对象。因此,我们可以在测试中模拟出 `getCleanTasks` 方法的返回值,来验证 `pollTasks` 方法的正确性。 当然,这只是针对一个小小的方法的测试,你还需要根据代码的实际情况编写更多的测试用例,以确保代码的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值