《测试驱动的嵌入式C语言开发》——3.1节具有可测性的C模块的那些元素

简介: 本节书摘来自华章社区《测试驱动的嵌入式C语言开发》一书中的第3章,第3.1节具有可测性的C模块的那些元素,作者:(美)James W. Grenning,更多章节内容可以访问云栖社区“华章社区”公众号查看

3.1 具有可测性的C模块的那些元素
本书中的示例将采用模块这个概念。在我们的目的之下,模块就是系统中一个完备的部分,它有明确定义的接口。这个定义并没有讲一个模块有多大。在本书中,我们只会用很小的模块。这些示例中的模块会恰好与编译单元相同,然而在现实世界中,并不是所有的模块都与某个单一的编译单元相对应。你会发现可测试的代码需要模块化。你还会发现TDD会自然而然地产生模块化设计。
可测试性对于测试有相当大的正面影响。为了创建模块化的C程序,我们需要抽象数据类型这个概念。Barbara Liskov在她所著的《Programming with Abstract Data Types》[Lis74]一书中这样定义抽象数据类型(Abstract Data Type,ADT):“抽象数据类型只用可能对它进行的那些操作来间接定义,并且这些操作的效果(也可能是代价)有数学上的约束。”
在抽象数据类型(ADT)中,一个模块的数据被当做私有成员来对待。它被封装起来。我们可以使用几种模块化方法来封装模块的数据。第一个选择是用静态的只有在.c文件中可见的变量,这样只有同一编译单元中的函数才能访问它们。数据只能间接地通过在.h文件中有原型定义的那些模块的公共接口来访问。这个方式适用于只有一套数据需要处理的模块,有时称为单一实例模块(single-instance module)。
当一个模块要为不同的客户管理不同的数据时,可以使用多实例模块(multiple-instance module)。在多实例模块中,必须要初始化数据结构并把它传回给客户以保持其上下文。这里就是抽象数据类型发挥作用的地方。可以用typedef在头文件中提前声明结构体,像这样:


8347c4057d39cff9a6335a446a637f116e2c9027

只要没有代码去解引用它,编译器会很乐意让我们把定义不完全的指针传来传去。可以在实现CircularBuffer的.c文件中定义结构体的成员,这样就有效地隐藏了数据,从而使得只有那些以该数据结构的完备性为责任的模块才能操作它。如果你熟悉POSIX接口(Portable Operating System Interface of UNIX)中的pthread库,就会明白它使用的就是这种技术。Unix中的FILE(文件)是另一个抽象数据类型的例子。
当用TDD来创建C模块时,我们会用到以下文件及惯例:
用头文件来定义模块的接口。对于单一实例模块,头文件由函数原型构成。对于抽象数据类型,除了函数原型,还会有一个用typedef来指向提前声明的数据结构的指针。正如多次提到的,隐藏数据结构是为了隐藏模块的数据细节。
源文件用来包含对接口的实现。它同时会包含任何所需的私有辅助函数和隐藏的数据。模块的实现会管理模块数据的完备性。对于抽象数据类型,提前声明的数据结构成员会在源文件中定义。
测试文件用来包含测试用例,以保持测试代码和产品代码分离。每个模块都至少有一个测试文件,一个测试文件通常仅包含一个,但有时会是几个测试组。测试组围绕组中所有测试通用的数据来组织。当一些测试需求的建立与其他测试显著不同时,我们就需要有多个测试组,甚至多个测试文件。
模块初始化及清理函数。每个管理着隐藏数据的模块都应该有初始化及清理函数。抽象数据类型完全隐藏的内部结构必然需要它们。C++把这个想法内置到构建和析构函数中。按照惯例,本书会为每个模块建立Create(创建)和Destroy(销毁)函数。对于由独立函数组成的模块,如strlen()和sprintf()这样的没有内部状态的模块将不会需要初始化与清理。
遵循这些实践及习惯,代码将变得更容易测试并容易阅读和扩展。并不是完全不能测试那些可以随意访问数据结构/函数的代码,只是那会更难一点。在第一个例子中,本书将会用单一实例模块来测试驱动开发一个LED(发光二极管)驱动程序。我们以后再使用抽象数据类型。

相关文章
|
2月前
|
安全 Linux 网络安全
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(一)
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(一)
|
2月前
|
Python Windows 网络安全
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(二)
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(二)
|
4月前
|
缓存 运维 数据库
【测试人员兼职指南】利用专业技能:如何从测试转向开发赚钱
本文分享了作者作为测试人员如何利用专业技能转向开发来兼职赚钱的经验,包括分析和解决登录页面跳转、避免重复账号注册、用户登录后首页显示用户名以及添加退出功能等问题,并提供了Django项目中使用sqlite3数据库和后台管理的扩展技巧。
133 1
【测试人员兼职指南】利用专业技能:如何从测试转向开发赚钱
|
2月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
45 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
2月前
|
测试技术 网络安全
什么是软件测试? 软件测试都有什么岗位 ?软件测试和调试的区别? 软件测试和开发的区别? 一位优秀的测试人员应该具备哪些素质? 软件测试等相关概念入门篇
文章全面介绍了软件测试的基本概念、目的、岗位分类、与开发和调试的区别,并阐述了成为优秀测试人员应具备的素质和技能。
208 1
什么是软件测试? 软件测试都有什么岗位 ?软件测试和调试的区别? 软件测试和开发的区别? 一位优秀的测试人员应该具备哪些素质? 软件测试等相关概念入门篇
|
14天前
|
安全 测试技术 持续交付
云计算时代的软件开发与测试:高效、灵活、可扩展
云计算时代的软件开发与测试:高效、灵活、可扩展
|
2月前
|
人工智能 监控 测试技术
云应用开发平台测试
云应用开发平台测试
61 2
|
2月前
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
95 3
|
2月前
|
敏捷开发 测试技术
开发模型(瀑布、螺旋、scrum) 和 测试模型(V、W)、增量和迭代、敏捷(思想)及敏捷开发 scrum
文章详细介绍了软件开发过程中的不同开发模型(瀑布、螺旋、Scrum)和测试模型(V模型、W模型),以及增量和迭代的概念,最后阐述了敏捷思想及其在敏捷开发(如Scrum)中的应用。
80 0
开发模型(瀑布、螺旋、scrum) 和 测试模型(V、W)、增量和迭代、敏捷(思想)及敏捷开发 scrum
|
2月前
|
测试技术 PHP 开发工具
php性能监测模块XHProf安装与测试
【10月更文挑战第13天】php性能监测模块XHProf安装与测试
33 0