回归测试编写

来自 PostgreSQL wiki
跳转到导航跳转到搜索

为 PostgreSQL 编写新的回归测试

在尝试编写新的回归测试时,我发现关于这方面的文档缺乏。本文档是我尝试记录我学到的知识供将来参考。

文件布局

所有回归测试文件都位于 GIT 中的 pgsql/src/test/regress/

调度文件

  • parallel_schedule
  • serial_schedule
    • 这些文件由 pgsql/src/test/regress/pg_regress 可执行文件解析和处理。这些文件具有以下格式:空行和带尾部“#”符号的行将被忽略,以“test:”代码字开头的行定义要运行的测试,以“ignore:”代码字开头的行形成忽略列表。当 pg_regress 遇到忽略列表中的测试时,它会照常运行测试,但会忽略测试的失败。您可以在每个“ignore:”行中指定一个测试名称,以及每个“test:”行中最多指定 20 个测试名称。如果您在一个“test:”行中指定了多个名称,则这些测试将以并行模式运行(parallel_schedule 以这种方式执行)。如果只有一个测试名称,则该测试将以单一模式运行(serial_schedule 以这种方式执行)。parallel_schedule 用于运行 make check 命令。serial_schedule 用于 make installcheck。如果您想添加新的回归测试,则应将其名称添加到 parallel_scheduleserial_schedule 中。

测试的 SQL 代码和预期结果

  • sql/
    • 该目录包含测试工具将运行的 sql 脚本。回归测试工具的输出将每个文件列为单独的测试项,因此习惯上每个 sql 文件测试一个“功能”。
  • expected/
    • 该目录包含 *.out 文件,其中包含每个回归脚本的预期输出。输出文件除包含任何查询的结果外,还包含 sql 文件的内容,包括任何注释。
  • results/
    • 该目录虽然不包含任何用户生成的文件,但包含回归脚本运行后的输出。这里的 *.out 文件通常可以在编写新测试时复制到 expected/ 目录中。

特殊测试

  • input/
  • output/
    • 包含 *.source 文件,这些文件需要在分别变为 *.sql*.out 文件之前进行预处理。
  • data/
    • 需要数据文件的测试(目前仅限于复制测试,不过 目前也正在开发一个大型对象测试)将它们存储在该目录中。需要访问该目录中文件的测试需要利用上面的预处理机制,并将该目录引用为 @abs_srcdir@/data/,它将被替换为数据目录的绝对路径。

替换变量

  • @abs_srcdir@
    • 源代码树中 src/test/regress 目录的绝对路径
  • @abs_builddir@
    • 构建树中 src/test/regress 目录的绝对路径,在 VPATH 构建(即在源代码树之外构建)中,它与源代码树不同。
  • @testtablespace@
  • @DLSUFFIX@

示例测试

为了说明回归测试是如何构建的,我将创建一个简单的(虽然毫无意义)测试来展示它是如何完成的。

sql/simple.sql

该脚本是将要运行的实际回归测试

--
-- A simple brain-dead test to show how one is written
--

-- Create a table
CREATE TABLE simple_test (a integer, b text);

-- Add a couple of rows
COPY simple_test FROM stdin;
1	foo
2	bar
3	baz
4	floob
\.

-- Select it back out in reverse order
SELECT * FROM simple_test ORDER BY a DESC;

-- remove a row
DELETE FROM simple_test WHERE length(b) > 3;

-- Select again
SELECT * FROM simple_test ORDER BY a DESC;

-- Clean up
DROP TABLE simple_test;

expected/simple.out

该文件包含上面回归脚本的预期输出

--
-- A simple brain-dead test to show how one is written
--
-- Create a table
CREATE TABLE simple_test (a integer, b text);
-- Add a couple of rows
COPY simple_test FROM stdin;
-- Select it back out in reverse order
SELECT * FROM simple_test ORDER BY a DESC;
 a |   b   
---+-------
 4 | floob
 3 | baz
 2 | bar
 1 | foo
(4 rows)

-- remove a row
DELETE FROM simple_test WHERE length(b) > 3;
-- Select again
SELECT * FROM simple_test ORDER BY a DESC;
 a |  b  
---+-----
 3 | baz
 2 | bar
 1 | foo
(3 rows)

-- Clean up
DROP TABLE simple_test;

parallel_schedule

simple 测试需要添加到调度中才能运行。找到一个可能的组并将其添加到列表中。我将其放在“第四组并行测试”中。

这是将它添加到该组的 cvs diff。当您尝试时它可能不再适用,因为该文件可能会在 CVS 中更改。这仅作为将新测试放入其中的示例,因此不要过分认真对待它。

@@ -79,7 +79,7 @@
 # ----------
 # Another group of parallel tests
 # ----------
-test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update namespace prepared_xacts delete
+test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update namespace prepared_xacts delete simple
 
 # ----------
 # Another group of parallel tests

serial_schedule

该调度用于 make installcheck。将您的测试放在该文件中,顺序与 parallel_schedule 大致相同,以便于维护。关于 parallel_schedule 修补程序的相同注释也适用于此修补程序。

Index: serial_schedule
===================================================================
RCS file: /home/jeremyd/local/postgres/cvsuproot/pgsql/src/test/regress/serial_schedule,v
retrieving revision 1.33
diff -c -r1.33 serial_schedule
*** serial_schedule     30 Aug 2006 23:34:22 -0000      1.33
--- serial_schedule     24 Sep 2006 23:52:05 -0000
***************
*** 76,81 ****
--- 76,82 ----
  test: hash_index
  test: update
  test: delete
+ test: simple
  test: namespace
  test: prepared_xacts
  test: privileges

更新现有的回归测试

更新现有回归测试的典型方法是:向 sql/foo.sql 文件中写入新的命令,运行一次测试套件,检查失败;如果一切都如您所愿,将 results/foo.out 文件复制到 expected/,然后再次运行测试套件,现在希望一切都能通过。只要您没有处理任何从 source/output/ 构建的特殊测试,或者没有变体预期文件,这种方法就很好。然后您需要将差异合并到这些不同的文件中。包 rcs 中的“merge”命令可以提供帮助,例如:

merge output/largeobject.source expected/largeobject.out results/largeobject.out

或者

merge expected/json_1.out expected/json.out results/json.out

(在将 results/json.out 复制到 expected/json.out 之前)。