美文网首页
0基础——c/c++程序的测试笔记(一)

0基础——c/c++程序的测试笔记(一)

作者: ayusong870 | 来源:发表于2020-02-26 20:27 被阅读0次

要点

基于VS2015的计算代码度量值以及单元测试

新建样例

  1. 在VS2015中新建win32 控制台应用程序,选择空项目。


    新建项目
  2. 新建main.cpp代码内容如下:
#include<iostream>
#include<string>
using namespace std;

int main() {
    int a;
    cout << "你好!请选择 ...\n" << "0 : 我是新手\n" << "1 : 我做过类似的事情\n" << "2 : 我经验丰富\n";
    cout << "请选择(0-2):";
    cin >> a;
    switch (a) {
        case 0: 
            cout << "请进入新手村......";
            break;
        case 1: 
            cout << "即将进入能力测试.....";
            break;
        case 2:
            cout << "即将到达战场......";
            break;
        default:
            cout << "非法入侵....GM即将到达......";
    }
    system("pause");
    return 0;
}

配置项目

  1. 右键单击项目,选择属性。
  2. 在配置属性面板中,选择常规,一定要保证,如果所示的 公共语言运行时支持要选择 公共语言运行时支持(/clr),目的是为了让程序编译时在Debug模式下托管代码。否则分析计算代码度量值时,会有未包含托管代码的错误提示(如图)。
    属性页-配置常规内容
    未包含托管代码的错误提示
  3. 在配置属性面板中,选择代码分析,常规。选中生成时启动代码分析,在运行此规则集中可以配置具体要检查的规则。
    生成时启动代码分析

编译项目

  1. 为了演示编译结果,在main函数后面添加了一段代码:
   int b = 5;
   if (a == 0) {
       int b = 7;
       cout << b;
   }
  1. 在Debug模式下,编译项目。
1>------ 已启动生成: 项目: MyTest, 配置: Debug Win32 ------
1>  main.cpp
1>  正在运行 C/C++ 代码分析...
1>  正在生成代码...
1>  .NETFramework,Version=v4.0.AssemblyAttributes.cpp
1>  MyTest.vcxproj -> D:\tools\others\others\MyTest\Debug\MyTest.exe
1>  MyTest.vcxproj -> D:\tools\others\others\MyTest\Debug\MyTest.pdb (Full PDB)
1>  代码分析完成 -- 0 个错误,0 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
  1. 编译没有错误,也没有警告。但是VS在Debug目录下生成了main.nativecodeanalysis.xml文件。在这里更详细的记录了源码的警告信息。该信息中提示我后来新加的代码中在if代码段中声明的新变量b,与if代码段外面的变量b重名。不符合规范,但不影响程序运行,也没有产生正常的警告信息。
<?xml version="1.0" encoding="UTF-8"?>
<DEFECTS>
  <DEFECT>
    <SFA>
      <FILEPATH>d:\tools\others\others\mytest\mytest\</FILEPATH>
      <FILENAME>main.cpp</FILENAME>
      <LINE>25</LINE>
      <COLUMN>6</COLUMN>
    </SFA>
    <DEFECTCODE>6246</DEFECTCODE>
    <DESCRIPTION>“b”的局部声明遮蔽了外部作用域中具有相同名称的声明。有关其他信息,请参见此前位于“23”行(“d:\tools\others\others\mytest\mytest\main.cpp”中)的声明。</DESCRIPTION>
    <FUNCTION>main</FUNCTION>
    <DECORATED>?main@@$$HYAHXZ</DECORATED>
    <FUNCLINE>4</FUNCLINE>
    <PATH>
      <SFA>
        <FILEPATH>d:\tools\others\others\mytest\mytest\</FILEPATH>
        <FILENAME>main.cpp</FILENAME>
        <LINE>23</LINE>
        <COLUMN>7</COLUMN>
      </SFA>
    </PATH>
  </DEFECT>
</DEFECTS>
  1. 通过VS生成的XML文件中,我们可以了解到源码中的所藏匿的安全隐患。

计算代码度量值

  1. 右键单击解决方案,选择计算代码度量值


    选择计算代码度量值
  2. VS自动计算出main.cpp中的main函数的代码度量值


    计算结果
  3. 因为switch中有4个分支,新添加的if有一个分支,所以圈复杂度为5。程序编译后的代码行数为18行,可维护性指数为55。

单元测试

  1. 为了方便测试,新建Player.h和Player.cpp两个文件,文件内容如下。
//Player.h
namespace Role {
    class Player {
    private:
        int level;
        float exp;
        float hp;
        float atk;
        bool isUpLevel();
        void upLevel(float);
        void setExp(float);
        void setHP(float);
        void setATK(float);
        void setLevel(int);
    public:
        Player();
        void addExp(int);
        float getExp();
        float getHP();
        float getATK();
        int getLevel();
    };
}
//Player.cpp
#include "Player.h"
using namespace Role;
Player::Player() {
    setLevel(1);
    setHP(1.0);
    setATK(1.0);
    setExp(0.0);
}
/*private function*/
//是否具备升级条件
bool Player::isUpLevel() {
    float up_exp = getLevel() * 10.0f;
    if (getExp() > up_exp) {
        upLevel(up_exp);
        return true;
    }
    return false;
}
//执行升级
void Player::upLevel(float cost) {
    setLevel(getLevel() + 1);
    setExp(getExp()-cost);
    setHP(getHP() + getLevel()*5);
    setATK(getATK() + getLevel() * 1);
}
//setter
void Player::setExp(float data) {
    exp = data;
}
//setter
void Player::setHP(float data) {
    hp = data;
}
//setter
void Player::setATK(float data) {
    atk = data;
}
//setter
void Player::setLevel(int data) {
    level = data;
}
/*public function*/
//增加经验值
void Player::addExp(int data) {
    setExp(getExp() + data);
}
//获取玩家的经验值
float Player::getExp() {
    return exp;
}
//获得玩家的HP
float Player::getHP() {
    return hp;
}
//获得玩家的攻击值
float Player::getATK() {
    return atk;
}
//获得玩家等级
int Player::getLevel() {
    return level;
}
  1. 编译新添加的代码,会在Debug目录下生成Player.obj

  2. 右键单击解决方案,选择添加->新项目


    在解决方案中添加新项目
  3. 添加托管测试项目


    添加托管测试项目
  4. 右键选择新建的TestProject,选择属性,编辑链接器的输入项。在附加依赖项中,将生成的Player.obj添加进来。


    添加Player.obj
  5. 在测试项目的UnitTest.cpp中添加Player的头文件

#include "../MyTest/Player.h"
using namespace Role;
  1. 测试代码添加到如下代码中
[TestMethod]
        void TestMethod1()
        {
            //
            // TODO:  在此处添加测试逻辑
            //
            Player player;// = Player();
            player.addExp(11);
            int expect = 2;
            Assert::AreEqual(expect,player.getLevel() );
        };
  1. 运行所有测试,显示未通过,应为2,实际为1。这是为什么呢?因为我们调用了addExp,而在addExp中没有判断是否升级了,所以我们还需要添加isUpLevel判断一下是否升级,才会执行升级操作。


    测试未通过
  2. 在addExp中添加isUpLevel。

void Player::addExp(int data) {
    setExp(getExp() + data);
    isUpLevel();
}
  1. 重新编译Player.cpp,再次运行测试,这回顺利通过测试了。


    通过测试

相关文章

网友评论

      本文标题:0基础——c/c++程序的测试笔记(一)

      本文链接:https://www.haomeiwen.com/subject/cvkbchtx.html