蜕变测试的指导和分析.
蜕变测试是一套复杂完整的测试, 用来测试嵌入在 PostgreSQL 里的的 SQL 实现. 它同时测试标准 SQL 操作和PostgreSQL的扩展SQL. 这个套件最初是 Jolly Chen 和 Andrew Yu开发的,并且由 Marc Fournier 和 Thomas Lockhart 进行了大量的改进和重新封装. 自 PostgreSQL 6.1 以上开始, 这个蜕变测试包含在每个正式发布版本里.
蜕变测试可以就一套已经安装好并且在运行的服务器进行测试, 也可以就制作树里面临时安装的服务器进行测试.详细些说,有 “并行”和“串行”运行测试之分. 串行模式顺序运行每个测试,而并行模式启动多个服务器进程, 并行地运行一组测试. 并行测试使我们对进程内部通讯和锁的正确工作有足够的信心. 由于历史原因,串行测试通常对一个现存的安装进行测试,而并行 测试是“独立”的,不过这么做没有什么技术原因.
制作之后和安装之前运行蜕变测试,你可以在顶级目录键入
$ gmake check(或者你可以进入 src/test/regress 然后 在那里运行命令.) 这样将先制作几个辅助文件,比如平台相关的 “expected(预期)” 文件和一些用户定义的触发器函数,然后再运行测试驱动脚本. 最后你会看到类似下面的东西
====================== All 76 tests passed. ======================或者是一些关于某项测试失败的信息.参阅下面的 Section 12.1获取更多信息.
注意: 因为这个测试方法运行临时的服务器,所以如果你是 root 用户, 那这个方法不能运行(服务器不能以 root 身份启动). 如果你已经以 root 身份制作了,你就什么也干不了. 这时候你应该把测试目录的权限变成某个用户可以写, 然后以那个用户身份登陆,再开始测试.比如,
root# chmod -R a+w src/test/regress root# su - joeuser joeuser$ gmake check(这里唯一可能的“安全隐患”就是那个用户可能会背着你 修改蜕变测试的结果.用你的常识管理用户权限.)如果不是上面那样,安装后就可以运行测试.
小技巧: 在某些系统上,缺省的 Bourne 兼容的 shell(/bin/sh) 在管理太多并行的子进程的时候会出乱子.这可能导致并行测试锁住或者失败. 出现这种情况时,请在命令行上声明另外一个 Bourne 兼容的 shell,比如:
$ gmake SHELL=/bin/ksh check
安装后(参阅 Chapter 1)运行测试, 初始化一个数据区然后启动服务器,象我们在 Chapter 3 里面描述的那样,然后键入
$ gmake installcheck该测试将与在本地主机和缺省端口号上运行的服务器进行联接, 除非你用 PGHOST 和 PGPORT 环境变量设置为其它值.
有一些正确安装并且具有完整功能的 PostgreSQL可能会在一些蜕变测试中 “失效”, 这些主要是因为浮点数的形式和时区支持的问题.目前的测试只是简单的用 diff与参考系统的输出进行比较, 因而对一些细小的系统区别很敏感. 当一项测试报告"failed"("失败")时,只要检查一下预期和实际的结果, 你就会发现区别区别并不大. 当然,我们仍然在努力维护所有我们支持的平台的准确的参考文件, 这样我们就可以假定所有测试都通过.
蜕变测试的实际输出是在 src/test/regress/results 目录里的文件里.测试脚本使用 diff 以比较 每个输出文件和存放在 src/test/regress/expected 目录里的参考输出.任何区别都存放在 src/test/regress/regression.diffs 里面供你检查.(或者如果你愿意的话,你也可以自己运行 diff.)
有一些蜕变测试涉及到有意的非法输入值. 错误信息可能会来自PostgreSQL 代码或来自主机平台系统过程. 对于后者,信息可能在平台之间区别比较大,但应该反映相似的信息. 这些信息上的差别将会导致一个"失败"的蜕变测试, 我们可以通过检查文件发现这一点.
这个测试设计时是运行在纯 “C” 区域下的. 如果你在一套临时安装上运行测试,那么它应该不会造成任何问题, 因为蜕变测试程序会在 C 区域里启动服务器.但是,如果你在 一套已经安装好了的服务器上运行测试,而且该服务器用的不是 C 的区域设置,那么你可能就会看到因各种字串排序,数字格式和 货币数值等等问题造成的差异.
在一些区域设置里面,结果的差异非常小,很容易通过观察来检查. 但是,在一些修改了数字数值格式规则的区域里(通常交换了逗号 和小数点的用法),一些数值记录将测试失败,导致随后用到这些数据 的测试中大量差异的产生.
大多数日期和时间结果依赖于时区环境变量。参考文件是为时区 PST8PDT (伯克利,加州)准备的,因而如果测试没有设置为那个时区是显然会失败的。 蜕变测试的驱动器把环境变量 PGTZ设置为PST8PDT以保证正确的测试。 不过,你的系统必须为 PST8PDT 提供库支持, 否则与时区相关的测试将会失败.
$ env TZ=PST8PDT date上面的命令应该返回 PST8PDT 时区的当前时间.如果没有能用的 PST8PDT 数据库,那么你的系统可能会返回 GMT 的形式的时间. 如果没有可用的 PST8PDT 数据库,那么你可以明确设置时区规则:
PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
有些系统不能接受我们推荐的显式设置时区的语法; 在这样的机器上你可能要用不同的 PGTZ设置。
有些使用旧的时区库的系统在对 PDT 1970 年前的时间使用夏时制时会出毛病, 导致 PDT 1970 年以前的时间显示为 PST。 这会导致在测试结果里的本地化区别。
如果你在改为夏时制的日切日或者该天的前天或者后天测试时, 在 “timestamp” 测试里的一些查询可能失败. 这些查询假设昨天午夜, 今天午夜和明天午夜之间的间隔是精确的 24 小时... 如果是夏时制开始或结束的日切日,这些(假设)是错的.
有些测试涉及到对表中的数据列进行 64位(double precision) 计算的问题. 我们观察了涉及到计算double precision字段的数学函数的 结果的差别. float8 和 geometry(几何类型)测试尤其容易在不同平台之间产生小差别。 这时需要肉眼对这些差别进行比较, 以判断这些差别究竟有多大,我们发现是在小数点右边10位数。
有些系统在pow()和exp() 出错时产生的信号与目前 Postgres代码里期望的机制不一样.
有些测试涉及到关于加州奥克兰/伯克利街区图的地形数据. 这些地图数据是用多边形表达的,多边形的顶点使用一对 double precision 数据表示的(数字纬度和经度). 一开始,先创建一些表再把地理数据装入, 然后创建一些用多边形相交的操作符(##)连接的两个表的视图, 最后对视图进行选择操作.
当对比平台不同产生的差异时,发现差异发生在小数点右边第二位和第三位以后. 出现问题的 SQL 语句是下面几条:
SELECT * from street; SELECT * from iexit;
你可能会看见同样的元组以与预期文件的不同的顺序输出.在大多数情况下, 严格说来这不算臭虫.大多数蜕变测试脚本都不会迂腐到在每个 SELECT 中都使用 ORDER BY 的地步,因此根据 SQL 规范里的词汇的说明,它们的结果集的顺序 并非定义得非常好的.尤其是因为我们是在同样的数据上运行同样的查询, 因此我们在所有平台上通常都获得同样的结果, 因此即使缺少 ORDER BY 也不算什么大问题. 不过有些查询的确存在跨平台的排序问题. (如果你使用了非 C 的区域设置,也可能造成排序差异的问题.)
因此,如果你看到一个排序差异,应该不是什么要担心的问题(除非 出问题的查询的确使用了 ORDER BY).不过,如果有这样的现象,请告诉我们, 这样我们就可以在那条查询上加一个 ORDER BY, 这样我们就可以在以后版本里消除着种伪“失败”.
你可能会问,为什么我们不 ORDER 所有蜕变测试的 SELECT 以一次性消灭所有这类问题. 原因是这样做只能让蜕变测试用处更少,而不是更多,因为它们会试图使用 那些生成顺序结果的查询规划,而不再使用那些不排序的查询规划.
在“随机”测试脚本里至少有一个测试会产生随机结果. 这会导致蜕变测试中的随机测试失败(可能每五次到十次出现一次). 键入
diff results/random.out expected/random.out会产生仅仅一行或几行差别. 你不必担心这些,除非随机测试在重复测试中总是失败. (另一方面,如果在多次蜕变测试中随机测试 从不 失败,你可能也 应该 担心.)