初次使用单元测试后的体会

我们搞开发的往往觉得自己写的代码没问题,用不着测试,以前,我也这么认为,觉得测试浪费时间,也就没仔细研究过测试。

最近,闲来想试试单元测试,结合之前的编程经验,发现,单元测试至少是保证软件质量的最佳方式之一。一波一波程序员开发、维护一个产品,程序员之间的差别太大了,就像“明显没有错误”和“没有明显错误”的区别,怎么来保证产品在不断迭代中的质量,保留里面正确的部分,去掉bug呢?架构设计里面讲究面向接口,单元测试就能起到接口的作用。

通过单元测试的类,它的行为是符合当初单元设计的目标的。只要编写单元测试时,从多方面检验类的行为,就能确保在这样的情景下,类是符合设计的。在Vistual Studio中,最简单的单元测试就是使用本身自带的功能(不需要从网上找NUnit的程序集,直接在项目上引用"Microsoft.VisualStudio.QualityTools.UnitTestFramework"程序集就ok了)。还有另外一个好处,是方便调试。单元测试项目可以在测试运行时,对被测试类下断点,非常节约调试时间。

我是这么做的,单元测试的代码放到独立的项目中去,引用要测试的项目,在被测试项目中添加Assembly特性如下:

[assembly: InternalsVisibleTo("Projky.UnitTests")]

这样,单元测试就能对被测试项目中internal修饰符的类可见,又不破坏程序集的可见性。

举一个简单的需求,要将如“30d9132169211a45”或者“30-D9-13-21-69-21-1A-45”或者“30 D9 13 21 69 21 1A 45”这样的16进制字符串转换为Byte[]数组。设计了一个ByteString的类来实现需求。

internal class ByteString {
        public static Byte[] ConverterToBytes(string value) {
            if (value.IndexOf("-") > -1) {
                value = value.Replace("-", "");
            } else if (value.IndexOf(" ") > -1) {
                value = value.Replace(" ", "");
            }

            Debug.Assert(value.Length % 2 == 0, "Invalid byte string length.");

            List<Byte> list = new List<Byte>(value.Length / 2);

            for (int i = 0; i < value.Length; i += 2) {
                int bHi = GetInteger(value[i]);
                int bLow = GetInteger(value[i + 1]);
                Byte temp = (Byte)(bHi << 4 | bLow);
                list.Add(temp);
            }
            return list.ToArray();
        }

        static int GetInteger(char ch) {
            if (Char.IsDigit(ch)) {
                return ch - ‘0‘;
            }
            int value = 10;

            switch (ch) {
                case ‘a‘:
                case ‘A‘:
                 value = 10;
                 break;
                case ‘b‘:
                case ‘B‘:
                 value = 11;
                 break;
                case ‘c‘:
                case ‘C‘:
                 value = 12;
                 break;
                case ‘d‘:
                case ‘D‘:
                 value = 13;
                 break;
                case ‘e‘:
                case ‘E‘:
                 value = 14;
                 break;
                case ‘f‘:
                case ‘F‘:
                 value = 15;
                 break;
                default:
                 throw new NotSupportedException(ch.ToString() + " is not valid char.");
            }
            return value;
        }
    }

那么,简单验证该类的行为(接口)可以编写下面的测试类:

[TestClass]
    public class ByteStringTest {
        [TestMethod]
        public void ConverterToBytes() {
            string input = "30d9132169211a45";
            Byte[] bytes = ByteString.ConverterToBytes(input);
            Assert.IsTrue(bytes.Length == input.Length / 2);
            Assert.IsTrue(bytes[0] == 0x30);
            Assert.IsTrue(bytes[1] == 0xd9);
            Assert.IsTrue(bytes[2] == 0x13);
            Assert.IsTrue(bytes[3] == 0x21);
            Assert.IsTrue(bytes[4] == 0x69);
            Assert.IsTrue(bytes[5] == 0x21);
            Assert.IsTrue(bytes[6] == 0x1a);
            Assert.IsTrue(bytes[7] == 0x45);

            input = "30-D9-13-21-69-21-1A-45";
            bytes = ByteString.ConverterToBytes(input);
            Assert.IsTrue(bytes.Length == 8);
            Assert.IsTrue(bytes[0] == 0x30);
            Assert.IsTrue(bytes[1] == 0xd9);
            Assert.IsTrue(bytes[2] == 0x13);
            Assert.IsTrue(bytes[3] == 0x21);
            Assert.IsTrue(bytes[4] == 0x69);
            Assert.IsTrue(bytes[5] == 0x21);
            Assert.IsTrue(bytes[6] == 0x1a);
            Assert.IsTrue(bytes[7] == 0x45);

            input = "30 D9 13 21 69 21 1A 45";
            bytes = ByteString.ConverterToBytes(input);
            Assert.IsTrue(bytes.Length == 8);
            Assert.IsTrue(bytes[0] == 0x30);
            Assert.IsTrue(bytes[1] == 0xd9);
            Assert.IsTrue(bytes[2] == 0x13);
            Assert.IsTrue(bytes[3] == 0x21);
            Assert.IsTrue(bytes[4] == 0x69);
            Assert.IsTrue(bytes[5] == 0x21);
            Assert.IsTrue(bytes[6] == 0x1a);
            Assert.IsTrue(bytes[7] == 0x45);
        }
    }

如果单元测试运行失败,例如Assert.IsTrue()方法中,参数为False,则在VS中会抛异常,这样,就知道哪里不正确了。

注意用[TestClass]标记作为单元测试承载的类,是public可见性,而里面单个的独立测试方法,则采用[TestMethod]标记,同样是public可见性。

在Visual Studio里面还有一个技巧,按Ctrl + R,A可以自动运行单元测试项目。如果被测试类有断点的话,测试到该位置时,也会断下来。

初次使用单元测试后的体会,布布扣,bubuko.com

时间: 2024-10-27 00:29:42

初次使用单元测试后的体会的相关文章

实践GTD三周年后的体会

从2011年7月开始实践GTD到现在已经3年多了,按照年初设定的目标,应该写点GTD的体会,但提起笔来的时候却发现并没有什么太新的体会,大部分体会都已经在以前的文章中写到了,甚至有些流程已经简化了,看来这篇文章也就是把以前的文章再梳理一遍. 1.GTD到底是什么? GTD是一种时间管理的系统性方法,一方面让你全面掌控工作和生活中的事务,减轻焦虑,提高效率,另一方面让你把握视角,让你把主要精力集中在有意义的事情上. 这本<搞定III>中的下面这张图用2个维度说明了这种理念,水平方向上你用GTD的

(六) 初次使用单元测试心得

在新中大已经三年时间,一直在弄I6p 或者i6的产品,以及框架维护.虽然以前也听说过单元测试,但是在我的概念里面压根对测试的概念!而且新中大以产品开发为主,你要跑逻辑必须将DLL 覆盖到产品上才可以弄.压根没有所谓的单元测试的概念.   所以当斯凯网络的老大让我弄iOS的单元测试时,我还是挺反感的,一直对自己有过以下疑问: 为什么要测试 ? 若要测试自己弄个按钮跑一下代码不就好了?非要写什么单元测试呢?这不是事倍功半吗?多次一举吗? 然而当我用过单元测试之后,我才明白来.原来单元测试就是让你连按

第六章 读后心得体会

编写Linux驱动程序的步骤 第一步:建立Linux驱动骨架(装载和卸载Linux驱动). Linux驱动程序一般都需要指定module_init和module_exit,因此包含这两个函数及指定这两个函数的两个宏的C程序文件也可看作是Linux骨架. 第二步:注册和注销设备文件 分别使用misc_register和misc_deregister函数创建和移除设备文件. 第三步:指定与驱动相关的信息 通过MODULE_AUTHOR,MODULE_LICENSE,MODULE_ALLAS,MODU

第七章 读后心得体会

编写LED驱动 (1)       创建LED驱动的设备文件 第一步:使用cdev_init函数初始化cdev. 第二步:指定设备号. 第三步:使用cdev_add函数将字符设备添加到内核中的字符设备数组中. 第四步:使用class_create宏创建struct_class. 第五步:使用device_create函数创建设备文件. (2)       卸载LED驱动的设备文件 依次调用device_destroy, class_destroy, unregister_chrdev_regio

idea生成单元测试后运行报错:java.net.ConnectException: Connection refused:

从官网下载了一个最新的idea(2017.1.4 community),多一个一个类写了一个单元测试,测试代码都没写,然后运行测试,竟然报错,报错为Error connecting to 127.0.0.1:54305; reason: Connection refused: no further information: /127.0.0.1:54305 不知道链接54305端口是干什么的.有没有谁遇到过. 完整错误 : Error:Abnormal build process termina

第五章 读后心得体会

S3c6410开发板简介 S3c6410是由三星公司推出的低功耗,高性价比的RISC处理器,它基于ARM11内核,可广泛应用于移动电话和通用处理等领域. S3c6410为2.5G和3G通信服务提供了优化的硬件性能,内置强大的硬件加速器,包括运动视频处理,音频处理,2D加速,显示处理和缩放等.同时还集成了一个MFC. 安装串口调试工具:minicom OK6410开发板带了一个串口,可以通过串口线与PC连接.Linux驱动在输出调试信息的同时会通过串口线将调试信息发送到PC上,这样Linux驱动程

《构建之法》第一章概要及读后心得体会

1551427    钱洪章 首先知道:软件=程序+软件工程 名句:程序=数据结构+算法 提出疑问:"程序"是什么? 这里的程序指的是源程序,就是一行一行的代码. 软件够贱的过程:不仅仅是cc和link命令,一个复杂的软件不但要有合理的软件架构.软件设计与实现,还要有各种文件和数据来描述各个文件之间的依赖关系.编译参数.链接参数,等等. 新名词:源代码管理(配置管理).质量保障.软件测试.需求分析.软件维护.软件生命周期.软件项目的管理.软件的用户体验.商业模式 会得到一个扩展的推论:

第十章 读后心得体会

打印内核调试信息:printk printk函数的用法和printf函数类似,只不过printk函数运行在内核空间,printf函数运行在用户空间. 防止printk函数降低Linux驱动性能 虽然使用printk函数可以方便的将消息写入日志文件或控制台.但大量使用此函数频繁操作日志文件或控制台设备文件会严重影响Linux驱动的性能,因此,这就要求Linux驱动只在开发阶段使用printk函数输出消息,在正式发布Linux驱动时将可能形象性能的printk函数去掉. 通过虚拟文件系统进行数据交互

第八章 读后心得体会

一.Linux驱动的代码重用 1. 编译是由多个文件组成的Linux驱动 模拟环境:/root/drivers/ch08/driver_shared/multi_file_driver 在multi_file_driver目录中有一个multi_file_driver_eclipse目录,该目录是eclipse工程目录. main.c是Linux驱动的主程序.在fun.c和product.c  product.h中定义和实现了在main .c中使用的函数.在main.c中通过extern关键字使