测试驱动的嵌入式C语言开发(TDD)(第1-3章)
前言
过去所有关于 TDD的书使用的都是 Java 或是高端动态语言
会帮助你打造更好的软件并让你从漫长的“测试再修正”过程中解放出来
不是为软件测试人员而写的,为嵌入式软件开发者写的
目标读者是嵌入式 C 语言程序员,但C 代码有浓郁的面向对象(C++)的风格
“测试替身”和“仿制对象”的概念很重要
第 1 章 测试驱动开发
测试驱动开发(TDD)是一种增量式软件开发技术:模块化待开发的软件系统,只增不减
- TDD 并不是一种测试技术,它是解决编程问题的一种方法
- DLP:后期调试式编程,代码先设计并写出,即代码“写完”之后才进行测试
- 发现bug的时间增加,找到bug根本原因时间也会增加,修改bug时间也会增加
TDD 微循环:TDD 的核心是由小步骤来不断重复的循环组成
- 重构:不断重复以下循环中每次的最后一步,在不改变当前外部行为的条件下对现有代码结构进行修改的过程,其目的是通过写易于理解、易于演化并且易于我们自己和他人维护的代码来让工作变简单
- 增加一个小的测试
- 运行所有的测试并期待新测试失败,也可能根本连编译都通不过
- 为了让测试通过来做一些小改动
- 运行所有的测试并期待新的测试通过
- 重构,以移除重复并改进代码的表达方式
- TDD 的节奏:红灯-绿灯-重构
- 重构:不断重复以下循环中每次的最后一步,在不改变当前外部行为的条件下对现有代码结构进行修改的过程,其目的是通过写易于理解、易于演化并且易于我们自己和他人维护的代码来让工作变简单
TDD的好处
- 产生的 bug 更少
- 调试时间更短
- 边际效应所带来的 bug 更少
- 内心的平静
- 改善设计
- 对进度的监控
- 有趣且回报丰厚
第 2章 测试驱动开发的工具和约定
TDD 依赖于测试自动化(automated unit testing)
- 自动化单元测试框架是一个软件包,需要以下能力
- 用于表述测试用例的通用语言;
- 用于表述期望结果的通用语言;
- 能够使用产品代码所用编程语言的功能;
- 能把所有的工程、系统或子系统中的单元测试用例收集到一起;
- 一个能运行全部或者部分测试用例的机制;
- 对于测试套件的成功和失败给出明确的报告;
- 对于失败的测试给出详细的报告
- 自动化单元测试框架是一个软件包,需要以下能力
Unity:一个全部用 C 实现的自动化测试框架
- 把测试做到什么程度是需要我们自己来判断
- Unity 中的测试夹具可以帮我们避免测试用例的重复,即将测试中重复的内容提取为函数
- 应该用一个简单的命令就可以构建并运行构建出来的测试可执行程序
CppUTest:一个用 C++实现的自动化单元测试框架
- CppUTest 是为了支持在多种操作系统上开发嵌入式软件而特别设计的
- 用 Unity 和 CppUTest 写出的单元测试几乎一模一样
- CppUTest 的一个优势是,测试是自动安装的
单元测试崩溃了怎么办:
- Unity 和 CppUTest 都提供了一个命令行参数来让测试运行于“冗余模式”(-v)。使用了-v,每个 TEST()在运行前都会先写出自己的名字
四阶段测试模式:
- 建立:创建测试的前置条件。
- 运行:对系统进行操作。
- 验证:检查预期的输出。
- 拆卸:把被测系统恢复到测试前的初始状态
第 3章 开始一个 C 语言模块
具有可测性的 C 模块的元素
- 可测试的代码需要模块化
- 为了创建模块化的 C 程序,我们需要抽象数据类型这个概念,Unix中的 FILE(文件)是另一个抽象数据类型的例子
- 在抽象数据类型(ADT)中,一个模块的数据被当做私有成员来对待
- 单一实例模块(single-instance module),将私有变量封装起来只在.c里面使用,可以在.h里面引用
- 多实例模块(multiple-instancemodule),要初始化数据结构并把它传回给客户以保持其上下文,这里就是抽象数据类型发挥作用的地方,用法见 POSIX 接口中的 pthread 库
- 用 TDD 来创建 C 模块时,我们会用到以下文件及惯例
- 头文件:定义模块的接口
- 源文件:包含对接口的实现、任何所需的私有辅助函数和隐藏的数据
- 测试文件:测试用例,和产品代码分离,每个模块至少有一个测试文件
- 模块初始化及清理函数,由独立函数组成的模块不需要
开始一个LED测试
- 写一个测试列表,注意报酬递减,即当列表差不多时候可以去测试驱动,驱动设计同时想到什么测试需求再写到列表上
- 问题中最难的那部分解决掉,小问题自然会迎刃而解
- 测试程序包含两个文件:
- LedDriverTest.c,驱动测试文件,包含测试前、后、过程中函数
- LedDriverTestGroupRunner.c,测试组容器,各个需求角度的测试
- 在软硬件集成时我们要去看 LED,但是在单元测试时我们可以虚拟地来看它们
- 一个设计目标是 LedDriver 必须独立于硬件可测,为驱动程序伪造环境
- 依赖注入:LedDriver 的可重用性更好
- 不要让编码跑到测试前面,原则是产生被全面的测试用例彻底测试过的产品代码
先测试驱动接口再测试驱动内部实现
- 注于接口意味着我们是从外向内开发代码的
- 测试驱动开发的三个原则
- 除非是让一个失败的单元测试通过,否则不要写产品代码
- 不要写比足以失败更多的单元测试,构建失败也可以
- 不要写比足以让单元测试通过更多的产品代码
- 在有测试要求之前就增加代码会增加复杂度,而且对需求的理解可能是错的
增量式前进
- DTSTTCPW DTSTTCPW:意为在可行方案中选取最简单的方案执行
- 保持小而专注的测试
- 唯一可以安全地进行重构的时刻是当所有的测试都通过时
- 发现测试中的错误:你本来预期得到一个测试失败但它却通过了
测试要做到 FIRST
- Fast(快速的)
- Isolated(独立的)
- Repeatable(可重复的)
- Self-verifying(自校验的)
- Timely(及时的)
测试驱动的嵌入式C语言开发(TDD)(第1-3章)相关推荐
- uml+oopc嵌入式c语言开发精讲_新的程序开发模式出现,传统的嵌入式C语言程序员快要灭绝了?...
来源:嵌入式时代@头条号 在2000年前后,嵌入式软件工程师有着一套非常具体的技能,他们通常是电气工程师,不仅了解底层硬件的工作原理,还可以在底层编写汇编代码或者C语言代码,以使系统满足实时需求.嵌入 ...
- uml+oopc嵌入式c语言开发精讲_嵌入式开发中更接近底层的汇编与C语言
分享本文,介绍下更接近硬件底层的C语言与汇编,解释 CPU 如何执行代码. 高级语言与低级语言 学习编程其实就是学习与计算机交流的语言.因为计算机不理解人类语言,通过编译器把人类写的代码转成二进制代码 ...
- 嵌入式Linux_C语言开发工具
C语言开发工具 开发工具和操作系统之间是相互促进的.相互发展的,操作系统离不开软件开发的支持,软件开发工具也离不开操作系统这个平台.Linux操作系统下Linux开发工具的开源方式,可以让大家拥有更多 ...
- uml+oopc嵌入式c语言开发精讲_当前火爆的嵌入式领域,为什么选择C语言作为开发语言?了解一下...
C语言和嵌入式C编程有什么区别?其区别在于嵌入式的C语言是跑在嵌入式的开发板上的,CPU和电脑不一样,所以编译器也是不一样的,生成的可执行程序也是不一样的.选择嵌入式开发语言归结于嵌入式系统开发的特点 ...
- 【读书笔记】UML+OOPC嵌入式C语言开发精讲-认识对象
文章目录 认识对象 自然界的对象( Natural Object) 软件对象(Software Object) 对象与函数 对象与类 构造器(Constructor) 认识对象 自然界的对象( Nat ...
- 嵌入式c语言开发闹钟,DIY小设计:智能闹钟的简单软硬件实现-嵌入式系统-与非网...
一.项目概述 1.1 引言 你还在为早上闹钟叫不醒你而发愁吗?你还在为早上突然的闹铃声而烦吗?你还在为早上睁开眼睛时刺眼的灯光而伤脑筋吗?你还在为早上忘记重要事情不愿起床耽误行程而后悔吗?我们团队设计 ...
- 嵌入式c语言开发闹钟,嵌入式电子闹钟()时钟课程设计.doc
#include //头文件 #include #define uchar unsigned char //宏定义 #define uint unsigned int //位定义 sbit rs=P2 ...
- 《嵌入式系统 - Zephyr开发笔记》 第2章 Zephyr 编译环境搭建(Linux)
原文地址 开发环境 主机: Ubuntu v18.04 Zephyr:V2.3.99 SDK:0.11.4 Date:2020-08-20 Zephyr 可以在 Windows/MAC/Linux 上 ...
- 测试驱动开发TDD使用心得
1.代码就是设计.测试代码他也是设计. 2.TDD不光是发现BUG的单体测试手段,他是事先防止BUG的方法.把代码的行为通过测试代码写出来,是保护代码的最好的方式. 3.使用TDD的话,虽然不能保证代 ...
最新文章
- TOPCODER SAM 686 div1 300
- 038_JavaScript对象
- QWidget: Must construct a QApplication before a QPaintDevice
- 【转】后勤常用查询报告
- 服务器生成文件怎么配置路径,npm run build生成的文件如何部署到服务器上
- pluto.ctl_Apache Pluto,Portlet Bridge和JSF 2.0集成示例教程
- 记一次 ORA-600 [12700] 故障案例
- java hashmap value排序_按照Value对HashMap排序
- 常用的oracle时间计算
- 云虚拟主机bch 和 云服务器bcc,云虚拟主机bch 和 云服务器bcc
- 区块链溯源系统开发:为何百度、阿里纷纷押注区块链溯源
- 系统体系结构-概念和框架
- 超级产品:喜茶,凭什么能估值90亿
- Springboot多数据源问题之 Could not resolve type alias ‘Blog‘.
- 机器学习基础 - [第四章:正则化](3)线性回归的正则化
- windows常用快捷键-简洁版
- 如何通过一张照片来获取ip地址?
- 在shell脚本中使用sed命令更改文件中两个相似参数的其中一个
- 新风系统风速推荐表_新风系统该如何选择管径、计算风速与全压?知道
- dbeaver快速找表
热门文章
- 暖风熏得游人醉,趁着假日小闲,也想做一回文人雅士
- 求取众数及重数的算法实现(Java)
- 人工智能Python有哪些应用方向?
- Linux设置启动图标
- java如何获取手机号码_java中如何提取一个字符串中的电话号码?
- Vue(组件间通信:props、自定义事件、全局事件总线、消息订阅与发布)
- 我的Electron个人学习笔记
- 技嘉x58支持服务器Cpu,x58主板可以配什么CPU?
- 腾讯轻量级服务器安装win7或者win10系统
- 当vue3+vite创建的项目,报错“找不到模块“@/utils/index”或其相应的类型声明”