编程语言测试综述

0 引言

编程语言作为构建一切软件的基础,被誉为系统软件“皇冠上的明珠”,而作为保障编程语言基础设施质量的测试技术则是让这颗明珠持续闪亮的“聚光灯”。随着现代编程语言的兴起,编程语言基础设施测试涵盖的组件也越来越多,不仅包含传统的编译器测试,同时还包含语言标准库、运行时、调试器、程序分析工具、构建工具、部署工具、IDE 等一系列语言组件的测试,如何保证质量,甚至是 10 倍质量,成为构建一套语言基础设施的难点,更成为一款商用编程语言的核心竞争力。

本文从编程语言及其基础设施的概念出发,结合工程化过程中遇到的测试难点,分别从学术界和工业界的角度,对编译器、标准库及其它工具链组件的测试技术做了重点介绍,最后总结了编程语言测试技术面临的机会和挑战。

如果您想要了解更多编程语言相关的测试技术,请记得持续关注我们哟!也非常欢迎您加入我们的编程语言技术社区SIG-编程语言测试小组,和我们一起深入探索编程语言测试技术。
加入方式:文末有小助手微信,添加并备注加入SIG-编程语言测试。

1 编程语言基础设施概述

如果说语言是人类进行沟通和交流的表达方式,凝聚了人类文明的千年历史。那么编程语言作为人机对话所必须的具有共同处理规则的沟通指令,则代表了一代又一代计算机科学家智慧的结晶。1946 年 2 月 14 日,世界上第一台通用计算机“ENIAC”在美国宾夕法尼亚大学诞生。迄今在通用计算机上,至少诞生了超过上千种的编程语言。这些编程语言因其设计的初衷和需要解决的问题不同,而具备了不同的语言特性及编程方式 [1]。

在旧约故事里,上帝将巴别塔建造者们的语言打乱,让他们再也不能明白对方的意思,并把他们分散到了世界各地。同物种间的跨语言沟通尚且需要翻译,更何况是跨物种的人机交互。

老彼得·勃鲁盖尔所画的《巴别塔》,1563 年 英文名:The Tower of Babel (Bruegel)
若要避免人机对话陷入 “鸡同鸭讲” 的尴尬,就必须依赖 “编译器” 或“解释器”将程序员编写的 “命题作文” 翻译成计算机所能识别并执行的二进制指令。而翻译时所遵守的规则即是语言规范。语言规范定义了标准化符号的组合规则、约束以及它们所需要执行的操作指令。每种编程语言都有自己的语言规范,且会随着语言特性的演进而持续演进。例如 C 语言规范包括有 C89、C99 标准等。

语言规范通常都是对语言的完整描述,但语言规范有时候并不会规定所有的内容。在《The Java® Language Specification》中并没有规定 GC(garbage collector)采用的具体算法。因此在实现的时候就可以采用 Mark-Sweep 或者其他的算法。对于同一种编程语言,可以有不同的实现。例如,对于 C 语言,有开源的 GCC 编译器,还有基于 LLVM 的 clang 编译器。

Java、C/C++、Python、Swift 等用户层面的编程语言被作为高级语言为大众所了解。每种高级语言都有其对应的编译器或者解释器。程序员使用高级语言进行编码大致需要经过 4 个步骤:编辑-编译-调试-执行,才能最终得到一段预期的可执行程序。为了支撑完成上述步骤,多数厂家都会提供相应的集成开发环境,即 IDE(Integrated Development Environment),例如微软的 Visual Studio,苹果的 Xcode 等,还有支持 Java 开发的 IDE 包括 IntelliJ IDEA 和 Eclipse 等。

IDE 通常包括编辑器、编译器、调试器在内的完整的开发环境。其中编辑器是程序员会交互最多的模块,它会提供包括工程管理、文件管理、字符编辑、字体设置、自动联想、智能化代码推荐、查找、替换、重构等功能,帮助程序员完成程序的编辑。IDE 通常还会提供对应的调试器,调试器的功能会包含有单步调试、查看变量、修改变量等,从而帮助程序员减少 bug。为了便于程序的开发,尤其是在嵌入式领域,部分 IDE 还会提供仿真器,这样即使在没有真实硬件的条件下,也可以进行程序的开发。

为了进行程序开发,每种编程语言都会提供丰富的库函数。例如:网络服务与通信、数据的压缩与解压、多媒体的音视频处理、数学库、并发库、密码服务、通用的操作系统服务、GUI 库等等。这些库通常会满足各个领域不同的开发要求。

除了库函数以外,一般的 IDE 还会提供一些辅助性的编程工具。部署工具、代码格式化工具、静态检查工具、包管理工具、性能调优工具。

编程语言的开发者为了推广语言,一般都会为程序员提供语言参考(Language Reference)、编程指南 (Programming Guide) 或者 tutorial,针对不同的国家,可能还会有不同语言, 来加快程序员对语言的学习。也会通过 IDE 提供在线的升级的功能,来加快新版本的推广。为了扩大语言的使用范围,编程语言一般都会发布多个操作系统的版本,支持 Windows/Linux 等多个操作系统。

综上所述,编程语言的基础设施不仅仅包括语言规范,还包括编译器、调试器、仿真器在内的 IDE,以及标准库和一些辅助性工具的完整工具链。

2 编程语言测试的难点

通常编程语言规范都比较复杂,拿 C 语言举例,其规范文档当前已超过 700 页,语言规范的复杂性给程序员的阅读和理解都带来了很大的困难。语言规范的语法部分通常会采用 BNF(Backus–Naur form)[2] 来描述。作为一种描述编程语言语法的体系,BNF 保证了语法部分通过了形式化的论证,但编程语言的语义部分并无保证。因此通常来说,编程语言的规范更多的是采用自然语言描述,规范的写作人员和阅读人员,对于规范的理解可能存在个体性偏差,从而给编程语言的测试带来困难。

编程语言的测试从实现角度来说也非常困难。仅从编译器的架构来看,一个编译器的实现可能会包含多个前端和多个后端。截止 2019 年,GCC 编译器的代码行数就已经达到了 1500 万行 [3],支持的后端多达 50 多种 [4],这对编程语言的测试也带来了很大的挑战。

编程语言的生存周期也都很长,例如,C 语言诞生于 1972 年,至今已经有接近 40 年的历史。发展至今,C 语言的实现都会保证向后兼容。想要验证 1500 万行代码是否正确的实现了 700 页的文档描述的内容,其实是非常困难的。虽然在语言规范中通常不会包含很多对编译优化的描述,但在实际的编程语言测试中,通常会把对编译器的功能验证看做对语言规范一致性的验证。

编程语言的标准库涉及的内容非常广泛,例如:网络通信会涉及协议,密码服务会涉及安全,数学库会涉及精度,通用的操作系统服务会涉及跨平台的实现,数据的压缩和解压会涉及算法。因此,对于语言标准库的测试会涵盖计算机领域各个方面的大量知识,造成测试的难度与广度,以及对多个领域的掌握要求会非常高。

由于大多数编程语言的实现会支持多个操作系统,因此会涉及到多个平台的安装、升级、一致性等的测试,以及多个版本的兼容性测试、IDE 集成及用户体验测试、用户手册的资料测试等,还会包含性能测试、交互测试、集成测试等等。

这里笔者尽量全面地罗列了编程语言测试相关的内容,但对语言的测试来说,重点仍然是编译器和标准库相关的测试。

3 编程语言测试的技术

3.1 编译器测试技术

3.1.1 学术界对编译器的测试

近十年来,来自不同国家的专家、学者在编译器测试领域开展了广泛的研究。从大连理工江贺教授 [5] 团队的研究数据 [6] 可见,编译器测试相关的论文数量比例按照国家、地区排序,中国处于第四位,远落后于排名第一的美国,但其中论文作者中,华人占比较高, 详情见图 1。
图 1:Left: The number of papers and ratio for countries/regions. Right: The most productive authors [6]
各个专家的研究成果在编译

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值