【转】PostgreSQL 回归测试

https://blog.csdn.net/postgrechina/article/details/49130603

回归测试是PostgreSQL的测试方法之一。

回归测试,需要事先定义好测试脚本(通常是SQL脚本,放在sql目录中),同时定义好调用执行测试脚本的预期正确输出文件(通常放在expected目录中)。

测试使用make check或make installcheck进行,它会通过pg_regress程序调用sql目录中的SQL,并收集输出结果(通常放到results目录中),最后pg_regress会对expected目录和results目录中的文件使用diff进行一一比较。

如果比较发现文件内容不一致,会将不一致的结果输出到regression.diffs文件中,并返回这个TEST CASE failed。

但是这种测试方法实际上有一些需要注意的地方,例如我们使用不同的本地化设置,时区可能得到的结果和期望的结果就不一样。另外有些不可预知的结果,例如随机值,数据的顺序,执行计划和优化器相关参数有关。这些因素都可能导致测试结果和预期不一致,那么我们就需要人为去修复这种failed。

 

PostgreSQL的主代码测试文件在src/test/regress目录中。

这个目录的结构如下:

 

 

postgres@digoal-> ll -rt

total 1.2M

-rw-r--r-- 1 postgres postgres  579 Jun 10 03:29 standby_schedule    测试standby的调度配置, 其实就是调度sql里的文件名

-rw-r--r-- 1 postgres postgres 2.3K Jun 10 03:29 serial_schedule   串行测试的调度配置

-rw-r--r-- 1 postgres postgres  937 Jun 10 03:29 resultmap  不同的测试平台的结果映射文件,因为不同平台某些测试结果可能不相同,所以一个expected文件不能支持所有的平台。例如浮点数测试。

-rwxr-xr-x 1 postgres postgres 4.4K Jun 10 03:29 regressplans.sh

-rw-r--r-- 1 postgres postgres  20K Jun 10 03:29 regress.c

-rw-r--r-- 1 postgres postgres  159 Jun 10 03:29 README

-rw-r--r-- 1 postgres postgres 2.7K Jun 10 03:29 pg_regress_main.c

-rw-r--r-- 1 postgres postgres 1.6K Jun 10 03:29 pg_regress.h

-rw-r--r-- 1 postgres postgres  69K Jun 10 03:29 pg_regress.c

-rw-r--r-- 1 postgres postgres 3.6K Jun 10 03:29 parallel_schedule  并行测试的调度配置

-rw-r--r-- 1 postgres postgres  624 Jun 10 03:29 Makefile

-rw-r--r-- 1 postgres postgres 5.6K Jun 10 03:29 GNUmakefile

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 output

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 input

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 data   一些测试数据

drwxrwxrwx 2 postgres postgres 4.0K Sep  7 14:51 sql   测试用到的SQL

drwxrwxr-x 2 postgres postgres 4.0K Sep  7 14:52 results   通过pg_regress调用sql目录中的脚本,得到的结果

drwxrwxrwx 2 postgres postgres 4.0K Sep  7 14:51 expected   执行sql目录中的文件对应的正确返回结果

 

 

上层目录结构如下,其中包含了一些其他的测试目标,例如隔离级别的测试,本地化测试,性能测试,线程安全测试。等。

 

 

postgres@digoal-> cd /opt/soft_bak/postgresql-9.4.4/src/test

postgres@digoal-> ll

total 36K

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 examples

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:41 isolation

drwxrwxrwx  6 postgres postgres 4.0K Jun 10 03:38 locale

-rw-r--r--  1 postgres postgres  389 Jun 10 03:29 Makefile

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:38 mb

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:38 performance

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 perl

drwxrwxrwx 10 postgres postgres 4.0K Sep  7 19:17 regress

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 thread

 

 

接下来我们看看PostgreSQL的回归测试程序pg_regress的用法,它不会安装到PGHOME/bin中,只在src/test/regress中存在。

 

 

$ cd src/test/regress

$ src/test/regress/pg_regress --help

PostgreSQL regression test driver

 

Usage:

  pg_regress [OPTION]... [EXTRA-TEST]...

 

Options:

  --config-auth=DATADIR     update authentication settings for DATADIR

  --create-role=ROLE        create the specified role before testing

  --dbname=DB               use database DB (default "regression")

  --debug                   turn on debug mode in programs that are run

  --dlpath=DIR              look for dynamic libraries in DIR

  --encoding=ENCODING       use ENCODING as the encoding

  --inputdir=DIR            take input files from DIR (default ".")

  --launcher=CMD            use CMD as launcher of psql

  --load-extension=EXT      load the named extension before running the

                            tests; can appear multiple times

  --load-language=LANG      load the named language before running the

                            tests; can appear multiple times

  --max-connections=N       maximum number of concurrent connections

                            (default is 0, meaning unlimited)

  --outputdir=DIR           place output files in DIR (default ".")

  --schedule=FILE           use test ordering schedule from FILE

                            (can be used multiple times to concatenate)

  --temp-install=DIR        create a temporary installation in DIR

  --use-existing            use an existing installation

 

Options for "temp-install" mode:

  --extra-install=DIR       additional directory to install (e.g., contrib)

  --no-locale               use C locale

  --port=PORT               start postmaster on PORT

  --temp-config=FILE        append contents of FILE to temporary config

  --top-builddir=DIR        (relative) path to top level build directory

 

Options for using an existing installation:

  --host=HOST               use postmaster running on HOST

  --port=PORT               use postmaster running at PORT

  --user=USER               connect as USER

  --psqldir=DIR             use psql in DIR (default: configured bindir)

 

The exit status is 0 if all tests passed, 1 if some tests failed, and 2

if the tests could not be run for some reason.

 

Report bugs to <pgsql-bugs@postgresql.org>.

 

 

回归测试用法:

在PostgreSQL源码根目录,或者源码的regress目录中执行如下:

 

 

make check    // 测试时需要初始化数据库集群

make installcheck  // 使用以及启动的数据库集群测试,不需要初始化数据库集群

 

以下同时测试主代码以及contrib的代码:

 

 

make check-world

make installcheck-world

 

 

如果要使用自定义的diff参数,可以设置一个环境变量,

例如:make check PG_REGRESS_DIFF_OPTS='-u'。

同时我们还可以使用不同的LOCALE进行测试。例如:

 

 

make check LANG=de_DE.utf8

make check NO_LOCALE=1

make check LANG=C ENCODING=EUC_JP

 

 

当我们要测试调度中不包含的测试SQL时,可以使用EXTRA_TESTS参数,至于这些脚本为什么默认不包含在调度中,可能是因为这些SQL脚本可能对平台的依赖比较严重,所以没有放到默认的测试中。例如:

 

 

make check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8

make check EXTRA_TESTS=numeric_big

 

 

接下来我们看看调度文件以及sql脚本目录:

 

 

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/src/test/regress

postgres@digoal-> less serial_schedule 

# src/test/regress/serial_schedule

# This should probably be in an order similar to parallel_schedule.

test: tablespace

test: boolean

test: char

test: name

test: varchar

test: text

test: int2

test: int4

test: int8

 

......

并行调度

postgres@digoal-> less parallel_schedule 

 

 

# ----------

# src/test/regress/parallel_schedule

#

# By convention, we put no more than twenty tests in any one parallel group;

# this limits the number of connections needed to run the tests.

# ----------

# run tablespace by itself, and first, because it forces a checkpoint;

# we'd prefer not to have checkpoints later in the tests because that

# interferes with crash-recovery testing.

test: tablespace

 

# ----------

# The first group of parallel tests

# ----------

test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn regproc

 

......

 

调度文件的test:后面跟的就是sql目录下的文件名(不含.sql后缀)。

 

 

postgres@digoal-> less sql/

total 1940

drwxrwxrwx  2 postgres postgres   4096 Sep  7 14:51 ./

drwxrwxrwx 10 postgres postgres   4096 Sep  7 22:34 ../

-rw-r--r--  1 postgres postgres   2237 Jun 10 03:29 abstime.sql

-rw-r--r--  1 postgres postgres   4097 Jun 10 03:29 advisory_lock.sql

-rw-r--r--  1 postgres postgres  20295 Jun 10 03:29 aggregates.sql

-rw-r--r--  1 postgres postgres  24882 Jun 10 03:29 alter_generic.sql

-rw-r--r--  1 postgres postgres  54461 Jun 10 03:29 alter_table.sql

-rw-r--r--  1 postgres postgres  17244 Jun 10 03:29 arrays.sql

-rw-r--r--  1 postgres postgres    594 Jun 10 03:29 async.sql

-rw-r--r--  1 postgres postgres   1365 Jun 10 03:29 bitmapops.sql

-rw-r--r--  1 postgres postgres   6406 Jun 10 03:29 bit.sql

-rw-r--r--  1 postgres postgres   4164 Jun 10 03:29 boolean.sql

 

......

所以前面提到的EXTRA_TESTS实际上也是sql目录中的文件名(不带.sql后缀)。

 

 

make check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8

make check EXTRA_TESTS=numeric_big

 

 

来实际的试一下吧:

 

 

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/src/test/regress

postgres@digoal-> make installcheck-parallel  //并行测试,使用已经开启的现有的数据库集群

make -C ../../../src/port all

......

../../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql9.4.4/bin'    --dlpath=.  --schedule=./parallel_schedule  

(using postmaster on /data01/pg_root_1921, port 1921)

============== dropping database "regression"         ==============

DROP DATABASE

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test tablespace               ... ok

......

parallel group (19 tests):  limit conversion sequence returning without_oid polymorphism copy2 xml prepare plancache rowtypes temp domain with truncate largeobject rangefuncs alter_table plpgsql

     plancache                ... ok

     limit                    ... ok

     plpgsql                  ... ok

     copy2                    ... ok

     temp                     ... ok

     domain                   ... ok

     rangefuncs               ... FAILED

     prepare                  ... ok

     without_oid              ... ok

     conversion               ... ok

     truncate                 ... ok

     alter_table              ... ok

     sequence                 ... ok

     polymorphism             ... FAILED

     rowtypes                 ... ok

     returning                ... ok

     largeobject              ... ok

     with                     ... FAILED

     xml                      ... ok

test stats                    ... ok

......

=========================

 22 of 145 tests failed. 

=========================

 

The differences that caused some tests to fail can be viewed in the

file "/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.diffs".  A copy of the test summary that you see

above is saved in the file "/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.out".

 

make: *** [installcheck-parallel] Error 1

 

有些测试失败了,diff文件已经输出到/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.diffs,我们可以查看一下看看为什么测试结果和预期结果不一致。

 

 

postgres@digoal-> less regression.diffs 

*** /opt/soft_bak/postgresql-9.4.4/src/test/regress/expected/pg_lsn.out 2015-06-10 03:29:38.000000000 +0800

--- /opt/soft_bak/postgresql-9.4.4/src/test/regress/results/pg_lsn.out  2015-09-07 22:45:04.413922536 +0800

***************

*** 72,92 ****

         generate_series(1, 5) k

    WHERE i <= 10 AND j > 0 AND j <= 10

    ORDER BY f;

!                                 QUERY PLAN                                

! --------------------------------------------------------------------------

!  Sort

!    Sort Key: (((((i.i)::text || '/'::text) || (j.j)::text))::pg_lsn)

!    ->  HashAggregate

!          Group Key: ((((i.i)::text || '/'::text) || (j.j)::text))::pg_lsn

           ->  Nested Loop

                 ->  Function Scan on generate_series k

!                ->  Materialize

!                      ->  Nested Loop

!                            ->  Function Scan on generate_series j

!                                  Filter: ((j > 0) AND (j <= 10))

!                            ->  Function Scan on generate_series i

!                                  Filter: (i <= 10)

! (12 rows)

  

  SELECT DISTINCT (i || '/' || j)::pg_lsn f

    FROM generate_series(1, 10) i,

--- 72,90 ----

         generate_series(1, 5) k

    WHERE i <= 10 AND j > 0 AND j <= 10

    ORDER BY f;

......

 

对于主代码,如果我们需要自定义测试SQL,我们可以修改regress/sql目录下的文件,或者新增文件。同时修改regress/expected目录下的对应期望文件,或者现在期望文件。

如果是新增文件的情况,我们还需要修改调度文件regress/serial_schedule和regress/parallel_schedule,把测试加入调度。

 

最后,再以ltree插件为例,看看如何配置一个外加插件的回归测试。

ltree的源码目录:

 

 

postgres@digoal-> cd contrib/

postgres@digoal-> cd ltree/

postgres@digoal-> ll -rt

total 1.1M

-rw-r--r-- 1 postgres postgres  517 Jun 10 03:29 Makefile

-rw-r--r-- 1 postgres postgres 2.4K Jun 10 03:29 ltxtquery_op.c

-rw-r--r-- 1 postgres postgres  11K Jun 10 03:29 ltxtquery_io.c

-rw-r--r-- 1 postgres postgres 7.9K Jun 10 03:29 ltree--unpackaged--1.0.sql

-rw-r--r-- 1 postgres postgres  994 Jun 10 03:29 ltreetest.sql

-rw-r--r-- 1 postgres postgres  13K Jun 10 03:29 ltree_op.c

-rw-r--r-- 1 postgres postgres 6.9K Jun 10 03:29 _ltree_op.c

-rw-r--r-- 1 postgres postgres  14K Jun 10 03:29 ltree_io.c

-rw-r--r-- 1 postgres postgres 7.3K Jun 10 03:29 ltree.h

-rw-r--r-- 1 postgres postgres  16K Jun 10 03:29 ltree_gist.c

-rw-r--r-- 1 postgres postgres  13K Jun 10 03:29 _ltree_gist.c

-rw-r--r-- 1 postgres postgres  155 Jun 10 03:29 ltree.control

-rw-r--r-- 1 postgres postgres  18K Jun 10 03:29 ltree--1.0.sql

-rw-r--r-- 1 postgres postgres 7.1K Jun 10 03:29 lquery_op.c

-rw-r--r-- 1 postgres postgres  263 Jun 10 03:29 crc32.h

-rw-r--r-- 1 postgres postgres 4.1K Jun 10 03:29 crc32.c

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 sql

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 expected

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 data

 

 

contrib/ltree的Makefile如下(在这里配置回归测试的调度,用到变量REGRESS,对应sql目录中的脚本文件名):

 

 

 

# contrib/ltree/Makefile

 

MODULE_big = ltree

OBJS =  ltree_io.o ltree_op.o lquery_op.o _ltree_op.o crc32.o \

        ltxtquery_io.o ltxtquery_op.o ltree_gist.o _ltree_gist.o

PG_CPPFLAGS = -DLOWER_NODE

 

EXTENSION = ltree

DATA = ltree--1.0.sql ltree--unpackaged--1.0.sql

 

REGRESS = ltree

 

ifdef USE_PGXS

PG_CONFIG = pg_config

PGXS := $(shell $(PG_CONFIG) --pgxs)

include $(PGXS)

else

subdir = contrib/ltree

top_builddir = ../..

include $(top_builddir)/src/Makefile.global

include $(top_srcdir)/contrib/contrib-global.mk

endif

 

其中:

 

 

 

include $(PGXS)

或 :

 

include $(top_builddir)/src/Makefile.global

 

 

都指向了:

 

 

src/makefiles/pgxs.mk

 

这个makefile中会用到回归测试相关的两个变量:

 

 

#   REGRESS -- list of regression test cases (without suffix)

#   REGRESS_OPTS -- additional switches to pass to pg_regress

 

引用src/makefiles/pgxs.mk的部分内容如下:

 

 

ifdef REGRESS

 

# Select database to use for running the tests

ifneq ($(USE_MODULE_DB),)

  REGRESS_OPTS += --dbname=$(CONTRIB_TESTDB_MODULE)

else

  REGRESS_OPTS += --dbname=$(CONTRIB_TESTDB)

endif

 

# where to find psql for running the tests

PSQLDIR = $(bindir)

 

# When doing a VPATH build, must copy over the data files so that the

# driver script can find them.  We have to use an absolute path for

# the targets, because otherwise make will try to locate the missing

# files using VPATH, and will find them in $(srcdir), but the point

# here is that we want to copy them from $(srcdir) to the build

# directory.

 

ifdef VPATH

abs_builddir := $(shell pwd)

test_files_src := $(wildcard $(srcdir)/data/*.data)

test_files_build := $(patsubst $(srcdir)/%, $(abs_builddir)/%, $(test_files_src))

 

all: $(test_files_build)

$(test_files_build): $(abs_builddir)/%: $(srcdir)/%

        $(MKDIR_P) $(dir $@)

        ln -s $< $@

endif # VPATH

 

.PHONY: submake

submake:

ifndef PGXS

        $(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)

endif

 

# against installed postmaster

installcheck: submake $(REGRESS_PREP)

        $(pg_regress_installcheck) $(REGRESS_OPTS) $(REGRESS)

 

ifdef PGXS

check:

        @echo '"$(MAKE) check" is not supported.'

        @echo 'Do "$(MAKE) install", then "$(MAKE) installcheck" instead.'

else

check: all submake $(REGRESS_PREP)

        $(pg_regress_check) --extra-install=$(subdir) $(REGRESS_OPTS) $(REGRESS)

endif

endif # REGRESS

 

 

这里用到了ltree中Makefile中定义的subdir 和 REGRESS变量,如下:

 

 

top_builddir = ../..

subdir = contrib/ltree

REGRESS = ltree

 

所以我们在contrib/ltree中执行make check会执行:(指PGXS未定义时)

 

 

        $(pg_regress_check) --extra-install=$(subdir) $(REGRESS_OPTS) $(REGRESS)

pg_regress_check这个变量在src/Makefile.global中定义了,其实就是pg_regress命令的调用:

 

src/Makefile.global

src/Makefile.global:srcdir = .

pg_regress_locale_flags = $(if $(ENCODING),--encoding=$(ENCODING)) $(NOLOCALE)

pg_regress_check = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --temp-install=./tmp_check --top-builddir=$(top_builddir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)

 

 

在contrib/ltree中执行make check最终执行的是(没有定义的变量直接忽略):

 

 

../../src/test/regress/pg_regress --inputdir=. --temp-install=./tmp_check --top-builddir=../.. --extra-install=contrib/ltree ltree

 

我们可以直接到ltree的源码目录测试这条命令:

 

 

[root@digoal ~]# chown -R postgres:postgres /opt/soft_bak/postgresql-9.4.4

[root@digoal ~]# su - postgres

postgres@digoal-> cd /opt/soft_bak/postgresql-9.4.4/contrib/ltree/

postgres@digoal-> ../../src/test/regress/pg_regress --inputdir=. --temp-install=./tmp_check --top-builddir=../.. --extra-install=contrib/ltree ltree

============== removing existing temp installation    ==============

============== creating temporary installation        ==============

============== initializing database system           ==============

============== starting postmaster                    ==============

running on port 57636 with PID 27852

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test ltree                    ... ok

============== shutting down postmaster               ==============

============== removing temporary installation        ==============

 

=====================

 All 1 tests passed. 

=====================

 

 

另外一种测试时installcheck,和check不同的是,installcheck不需要初始化数据库,是在我们开启了数据库集群的情况下的测试。

同样的方法,我们可以发现它调用的是:

 

 

        $(pg_regress_installcheck) $(REGRESS_OPTS) $(REGRESS)

 

通过src/Makefile.global的定义:

 

 

pg_regress_installcheck = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --psqldir='$(PSQLDIR)' $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)

bindir := $(shell $(PG_CONFIG) --bindir)

 

以及

 

 

src/makefiles/pgxs.mk

PSQLDIR = $(bindir)

 

最终转换为:

 

 

../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql/bin' ltree

 

启动数据库后,就可以进行测试了。同样需要注意(PGPORT PGHOST PGDATABASE PGUSER等)环境变量。

 

 

postgres@digoal-> pg_ctl start

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/contrib/ltree

postgres@digoal-> ../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql/bin' ltree

(using postmaster on /data01/pg_root_1921, port 1921)

============== dropping database "regression"         ==============

DROP DATABASE

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test ltree                    ... ok

 

=====================

 All 1 tests passed. 

=====================

 

所以插件的回归测试配置也很简单,同样需要sql, expected目录,以及通过配置Makefile来指定需要回归测试的sql脚本。

 

[参考]

1. http://www.postgresql.org/docs/devel/static/regress-run.html

2. http://www.postgresql.org/docs/devel/static/regress-variant.html

各种Makefile

src/Makefile.global

src/Makefile

src/makefiles/pgxs.mk 

contrib/contrib-global.mk 

contrib/xx/Makefile

......

代码覆盖率测试见我另一篇BLOG

http://blog.163.com/digoal@126/blog/static/1638770402015875295989/

回归测试是PostgreSQL的测试方法之一。

回归测试,需要事先定义好测试脚本(通常是SQL脚本,放在sql目录中),同时定义好调用执行测试脚本的预期正确输出文件(通常放在expected目录中)。

测试使用make check或make installcheck进行,它会通过pg_regress程序调用sql目录中的SQL,并收集输出结果(通常放到results目录中),最后pg_regress会对expected目录和results目录中的文件使用diff进行一一比较。

如果比较发现文件内容不一致,会将不一致的结果输出到regression.diffs文件中,并返回这个TEST CASE failed。

但是这种测试方法实际上有一些需要注意的地方,例如我们使用不同的本地化设置,时区可能得到的结果和期望的结果就不一样。另外有些不可预知的结果,例如随机值,数据的顺序,执行计划和优化器相关参数有关。这些因素都可能导致测试结果和预期不一致,那么我们就需要人为去修复这种failed。

 

PostgreSQL的主代码测试文件在src/test/regress目录中。

这个目录的结构如下:

 

 

postgres@digoal-> ll -rt

total 1.2M

-rw-r--r-- 1 postgres postgres  579 Jun 10 03:29 standby_schedule    测试standby的调度配置, 其实就是调度sql里的文件名

-rw-r--r-- 1 postgres postgres 2.3K Jun 10 03:29 serial_schedule   串行测试的调度配置

-rw-r--r-- 1 postgres postgres  937 Jun 10 03:29 resultmap  不同的测试平台的结果映射文件,因为不同平台某些测试结果可能不相同,所以一个expected文件不能支持所有的平台。例如浮点数测试。

-rwxr-xr-x 1 postgres postgres 4.4K Jun 10 03:29 regressplans.sh

-rw-r--r-- 1 postgres postgres  20K Jun 10 03:29 regress.c

-rw-r--r-- 1 postgres postgres  159 Jun 10 03:29 README

-rw-r--r-- 1 postgres postgres 2.7K Jun 10 03:29 pg_regress_main.c

-rw-r--r-- 1 postgres postgres 1.6K Jun 10 03:29 pg_regress.h

-rw-r--r-- 1 postgres postgres  69K Jun 10 03:29 pg_regress.c

-rw-r--r-- 1 postgres postgres 3.6K Jun 10 03:29 parallel_schedule  并行测试的调度配置

-rw-r--r-- 1 postgres postgres  624 Jun 10 03:29 Makefile

-rw-r--r-- 1 postgres postgres 5.6K Jun 10 03:29 GNUmakefile

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 output

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 input

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 data   一些测试数据

drwxrwxrwx 2 postgres postgres 4.0K Sep  7 14:51 sql   测试用到的SQL

drwxrwxr-x 2 postgres postgres 4.0K Sep  7 14:52 results   通过pg_regress调用sql目录中的脚本,得到的结果

drwxrwxrwx 2 postgres postgres 4.0K Sep  7 14:51 expected   执行sql目录中的文件对应的正确返回结果

 

 

上层目录结构如下,其中包含了一些其他的测试目标,例如隔离级别的测试,本地化测试,性能测试,线程安全测试。等。

 

 

postgres@digoal-> cd /opt/soft_bak/postgresql-9.4.4/src/test

postgres@digoal-> ll

total 36K

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 examples

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:41 isolation

drwxrwxrwx  6 postgres postgres 4.0K Jun 10 03:38 locale

-rw-r--r--  1 postgres postgres  389 Jun 10 03:29 Makefile

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:38 mb

drwxrwxrwx  4 postgres postgres 4.0K Jun 10 03:38 performance

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 perl

drwxrwxrwx 10 postgres postgres 4.0K Sep  7 19:17 regress

drwxrwxrwx  2 postgres postgres 4.0K Jun 10 03:38 thread

 

 

接下来我们看看PostgreSQL的回归测试程序pg_regress的用法,它不会安装到PGHOME/bin中,只在src/test/regress中存在。

 

 

$ cd src/test/regress

$ src/test/regress/pg_regress --help

PostgreSQL regression test driver

 

Usage:

  pg_regress [OPTION]... [EXTRA-TEST]...

 

Options:

  --config-auth=DATADIR     update authentication settings for DATADIR

  --create-role=ROLE        create the specified role before testing

  --dbname=DB               use database DB (default "regression")

  --debug                   turn on debug mode in programs that are run

  --dlpath=DIR              look for dynamic libraries in DIR

  --encoding=ENCODING       use ENCODING as the encoding

  --inputdir=DIR            take input files from DIR (default ".")

  --launcher=CMD            use CMD as launcher of psql

  --load-extension=EXT      load the named extension before running the

                            tests; can appear multiple times

  --load-language=LANG      load the named language before running the

                            tests; can appear multiple times

  --max-connections=N       maximum number of concurrent connections

                            (default is 0, meaning unlimited)

  --outputdir=DIR           place output files in DIR (default ".")

  --schedule=FILE           use test ordering schedule from FILE

                            (can be used multiple times to concatenate)

  --temp-install=DIR        create a temporary installation in DIR

  --use-existing            use an existing installation

 

Options for "temp-install" mode:

  --extra-install=DIR       additional directory to install (e.g., contrib)

  --no-locale               use C locale

  --port=PORT               start postmaster on PORT

  --temp-config=FILE        append contents of FILE to temporary config

  --top-builddir=DIR        (relative) path to top level build directory

 

Options for using an existing installation:

  --host=HOST               use postmaster running on HOST

  --port=PORT               use postmaster running at PORT

  --user=USER               connect as USER

  --psqldir=DIR             use psql in DIR (default: configured bindir)

 

The exit status is 0 if all tests passed, 1 if some tests failed, and 2

if the tests could not be run for some reason.

 

Report bugs to <pgsql-bugs@postgresql.org>.

 

 

回归测试用法:

在PostgreSQL源码根目录,或者源码的regress目录中执行如下:

 

 

make check    // 测试时需要初始化数据库集群

make installcheck  // 使用以及启动的数据库集群测试,不需要初始化数据库集群

 

以下同时测试主代码以及contrib的代码:

 

 

make check-world

make installcheck-world

 

 

如果要使用自定义的diff参数,可以设置一个环境变量,

例如:make check PG_REGRESS_DIFF_OPTS='-u'。

同时我们还可以使用不同的LOCALE进行测试。例如:

 

 

make check LANG=de_DE.utf8

make check NO_LOCALE=1

make check LANG=C ENCODING=EUC_JP

 

 

当我们要测试调度中不包含的测试SQL时,可以使用EXTRA_TESTS参数,至于这些脚本为什么默认不包含在调度中,可能是因为这些SQL脚本可能对平台的依赖比较严重,所以没有放到默认的测试中。例如:

 

 

make check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8

make check EXTRA_TESTS=numeric_big

 

 

接下来我们看看调度文件以及sql脚本目录:

 

 

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/src/test/regress

postgres@digoal-> less serial_schedule 

# src/test/regress/serial_schedule

# This should probably be in an order similar to parallel_schedule.

test: tablespace

test: boolean

test: char

test: name

test: varchar

test: text

test: int2

test: int4

test: int8

 

......

并行调度

postgres@digoal-> less parallel_schedule 

 

 

# ----------

# src/test/regress/parallel_schedule

#

# By convention, we put no more than twenty tests in any one parallel group;

# this limits the number of connections needed to run the tests.

# ----------

# run tablespace by itself, and first, because it forces a checkpoint;

# we'd prefer not to have checkpoints later in the tests because that

# interferes with crash-recovery testing.

test: tablespace

 

# ----------

# The first group of parallel tests

# ----------

test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn regproc

 

......

 

调度文件的test:后面跟的就是sql目录下的文件名(不含.sql后缀)。

 

 

postgres@digoal-> less sql/

total 1940

drwxrwxrwx  2 postgres postgres   4096 Sep  7 14:51 ./

drwxrwxrwx 10 postgres postgres   4096 Sep  7 22:34 ../

-rw-r--r--  1 postgres postgres   2237 Jun 10 03:29 abstime.sql

-rw-r--r--  1 postgres postgres   4097 Jun 10 03:29 advisory_lock.sql

-rw-r--r--  1 postgres postgres  20295 Jun 10 03:29 aggregates.sql

-rw-r--r--  1 postgres postgres  24882 Jun 10 03:29 alter_generic.sql

-rw-r--r--  1 postgres postgres  54461 Jun 10 03:29 alter_table.sql

-rw-r--r--  1 postgres postgres  17244 Jun 10 03:29 arrays.sql

-rw-r--r--  1 postgres postgres    594 Jun 10 03:29 async.sql

-rw-r--r--  1 postgres postgres   1365 Jun 10 03:29 bitmapops.sql

-rw-r--r--  1 postgres postgres   6406 Jun 10 03:29 bit.sql

-rw-r--r--  1 postgres postgres   4164 Jun 10 03:29 boolean.sql

 

......

所以前面提到的EXTRA_TESTS实际上也是sql目录中的文件名(不带.sql后缀)。

 

 

make check EXTRA_TESTS=collate.linux.utf8 LANG=en_US.utf8

make check EXTRA_TESTS=numeric_big

 

 

来实际的试一下吧:

 

 

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/src/test/regress

postgres@digoal-> make installcheck-parallel  //并行测试,使用已经开启的现有的数据库集群

make -C ../../../src/port all

......

../../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql9.4.4/bin'    --dlpath=.  --schedule=./parallel_schedule  

(using postmaster on /data01/pg_root_1921, port 1921)

============== dropping database "regression"         ==============

DROP DATABASE

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test tablespace               ... ok

......

parallel group (19 tests):  limit conversion sequence returning without_oid polymorphism copy2 xml prepare plancache rowtypes temp domain with truncate largeobject rangefuncs alter_table plpgsql

     plancache                ... ok

     limit                    ... ok

     plpgsql                  ... ok

     copy2                    ... ok

     temp                     ... ok

     domain                   ... ok

     rangefuncs               ... FAILED

     prepare                  ... ok

     without_oid              ... ok

     conversion               ... ok

     truncate                 ... ok

     alter_table              ... ok

     sequence                 ... ok

     polymorphism             ... FAILED

     rowtypes                 ... ok

     returning                ... ok

     largeobject              ... ok

     with                     ... FAILED

     xml                      ... ok

test stats                    ... ok

......

=========================

 22 of 145 tests failed. 

=========================

 

The differences that caused some tests to fail can be viewed in the

file "/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.diffs".  A copy of the test summary that you see

above is saved in the file "/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.out".

 

make: *** [installcheck-parallel] Error 1

 

有些测试失败了,diff文件已经输出到/opt/soft_bak/postgresql-9.4.4/src/test/regress/regression.diffs,我们可以查看一下看看为什么测试结果和预期结果不一致。

 

 

postgres@digoal-> less regression.diffs 

*** /opt/soft_bak/postgresql-9.4.4/src/test/regress/expected/pg_lsn.out 2015-06-10 03:29:38.000000000 +0800

--- /opt/soft_bak/postgresql-9.4.4/src/test/regress/results/pg_lsn.out  2015-09-07 22:45:04.413922536 +0800

***************

*** 72,92 ****

         generate_series(1, 5) k

    WHERE i <= 10 AND j > 0 AND j <= 10

    ORDER BY f;

!                                 QUERY PLAN                                

! --------------------------------------------------------------------------

!  Sort

!    Sort Key: (((((i.i)::text || '/'::text) || (j.j)::text))::pg_lsn)

!    ->  HashAggregate

!          Group Key: ((((i.i)::text || '/'::text) || (j.j)::text))::pg_lsn

           ->  Nested Loop

                 ->  Function Scan on generate_series k

!                ->  Materialize

!                      ->  Nested Loop

!                            ->  Function Scan on generate_series j

!                                  Filter: ((j > 0) AND (j <= 10))

!                            ->  Function Scan on generate_series i

!                                  Filter: (i <= 10)

! (12 rows)

  

  SELECT DISTINCT (i || '/' || j)::pg_lsn f

    FROM generate_series(1, 10) i,

--- 72,90 ----

         generate_series(1, 5) k

    WHERE i <= 10 AND j > 0 AND j <= 10

    ORDER BY f;

......

 

对于主代码,如果我们需要自定义测试SQL,我们可以修改regress/sql目录下的文件,或者新增文件。同时修改regress/expected目录下的对应期望文件,或者现在期望文件。

如果是新增文件的情况,我们还需要修改调度文件regress/serial_schedule和regress/parallel_schedule,把测试加入调度。

 

最后,再以ltree插件为例,看看如何配置一个外加插件的回归测试。

ltree的源码目录:

 

 

postgres@digoal-> cd contrib/

postgres@digoal-> cd ltree/

postgres@digoal-> ll -rt

total 1.1M

-rw-r--r-- 1 postgres postgres  517 Jun 10 03:29 Makefile

-rw-r--r-- 1 postgres postgres 2.4K Jun 10 03:29 ltxtquery_op.c

-rw-r--r-- 1 postgres postgres  11K Jun 10 03:29 ltxtquery_io.c

-rw-r--r-- 1 postgres postgres 7.9K Jun 10 03:29 ltree--unpackaged--1.0.sql

-rw-r--r-- 1 postgres postgres  994 Jun 10 03:29 ltreetest.sql

-rw-r--r-- 1 postgres postgres  13K Jun 10 03:29 ltree_op.c

-rw-r--r-- 1 postgres postgres 6.9K Jun 10 03:29 _ltree_op.c

-rw-r--r-- 1 postgres postgres  14K Jun 10 03:29 ltree_io.c

-rw-r--r-- 1 postgres postgres 7.3K Jun 10 03:29 ltree.h

-rw-r--r-- 1 postgres postgres  16K Jun 10 03:29 ltree_gist.c

-rw-r--r-- 1 postgres postgres  13K Jun 10 03:29 _ltree_gist.c

-rw-r--r-- 1 postgres postgres  155 Jun 10 03:29 ltree.control

-rw-r--r-- 1 postgres postgres  18K Jun 10 03:29 ltree--1.0.sql

-rw-r--r-- 1 postgres postgres 7.1K Jun 10 03:29 lquery_op.c

-rw-r--r-- 1 postgres postgres  263 Jun 10 03:29 crc32.h

-rw-r--r-- 1 postgres postgres 4.1K Jun 10 03:29 crc32.c

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 sql

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 expected

drwxrwxrwx 2 postgres postgres 4.0K Jun 10 03:38 data

 

 

contrib/ltree的Makefile如下(在这里配置回归测试的调度,用到变量REGRESS,对应sql目录中的脚本文件名):

 

 

 

# contrib/ltree/Makefile

 

MODULE_big = ltree

OBJS =  ltree_io.o ltree_op.o lquery_op.o _ltree_op.o crc32.o \

        ltxtquery_io.o ltxtquery_op.o ltree_gist.o _ltree_gist.o

PG_CPPFLAGS = -DLOWER_NODE

 

EXTENSION = ltree

DATA = ltree--1.0.sql ltree--unpackaged--1.0.sql

 

REGRESS = ltree

 

ifdef USE_PGXS

PG_CONFIG = pg_config

PGXS := $(shell $(PG_CONFIG) --pgxs)

include $(PGXS)

else

subdir = contrib/ltree

top_builddir = ../..

include $(top_builddir)/src/Makefile.global

include $(top_srcdir)/contrib/contrib-global.mk

endif

 

其中:

 

 

 

include $(PGXS)

或 :

 

include $(top_builddir)/src/Makefile.global

 

 

都指向了:

 

 

src/makefiles/pgxs.mk

 

这个makefile中会用到回归测试相关的两个变量:

 

 

#   REGRESS -- list of regression test cases (without suffix)

#   REGRESS_OPTS -- additional switches to pass to pg_regress

 

引用src/makefiles/pgxs.mk的部分内容如下:

 

 

ifdef REGRESS

 

# Select database to use for running the tests

ifneq ($(USE_MODULE_DB),)

  REGRESS_OPTS += --dbname=$(CONTRIB_TESTDB_MODULE)

else

  REGRESS_OPTS += --dbname=$(CONTRIB_TESTDB)

endif

 

# where to find psql for running the tests

PSQLDIR = $(bindir)

 

# When doing a VPATH build, must copy over the data files so that the

# driver script can find them.  We have to use an absolute path for

# the targets, because otherwise make will try to locate the missing

# files using VPATH, and will find them in $(srcdir), but the point

# here is that we want to copy them from $(srcdir) to the build

# directory.

 

ifdef VPATH

abs_builddir := $(shell pwd)

test_files_src := $(wildcard $(srcdir)/data/*.data)

test_files_build := $(patsubst $(srcdir)/%, $(abs_builddir)/%, $(test_files_src))

 

all: $(test_files_build)

$(test_files_build): $(abs_builddir)/%: $(srcdir)/%

        $(MKDIR_P) $(dir $@)

        ln -s $< $@

endif # VPATH

 

.PHONY: submake

submake:

ifndef PGXS

        $(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)

endif

 

# against installed postmaster

installcheck: submake $(REGRESS_PREP)

        $(pg_regress_installcheck) $(REGRESS_OPTS) $(REGRESS)

 

ifdef PGXS

check:

        @echo '"$(MAKE) check" is not supported.'

        @echo 'Do "$(MAKE) install", then "$(MAKE) installcheck" instead.'

else

check: all submake $(REGRESS_PREP)

        $(pg_regress_check) --extra-install=$(subdir) $(REGRESS_OPTS) $(REGRESS)

endif

endif # REGRESS

 

 

这里用到了ltree中Makefile中定义的subdir 和 REGRESS变量,如下:

 

 

top_builddir = ../..

subdir = contrib/ltree

REGRESS = ltree

 

所以我们在contrib/ltree中执行make check会执行:(指PGXS未定义时)

 

 

        $(pg_regress_check) --extra-install=$(subdir) $(REGRESS_OPTS) $(REGRESS)

pg_regress_check这个变量在src/Makefile.global中定义了,其实就是pg_regress命令的调用:

 

src/Makefile.global

src/Makefile.global:srcdir = .

pg_regress_locale_flags = $(if $(ENCODING),--encoding=$(ENCODING)) $(NOLOCALE)

pg_regress_check = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --temp-install=./tmp_check --top-builddir=$(top_builddir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)

 

 

在contrib/ltree中执行make check最终执行的是(没有定义的变量直接忽略):

 

 

../../src/test/regress/pg_regress --inputdir=. --temp-install=./tmp_check --top-builddir=../.. --extra-install=contrib/ltree ltree

 

我们可以直接到ltree的源码目录测试这条命令:

 

 

[root@digoal ~]# chown -R postgres:postgres /opt/soft_bak/postgresql-9.4.4

[root@digoal ~]# su - postgres

postgres@digoal-> cd /opt/soft_bak/postgresql-9.4.4/contrib/ltree/

postgres@digoal-> ../../src/test/regress/pg_regress --inputdir=. --temp-install=./tmp_check --top-builddir=../.. --extra-install=contrib/ltree ltree

============== removing existing temp installation    ==============

============== creating temporary installation        ==============

============== initializing database system           ==============

============== starting postmaster                    ==============

running on port 57636 with PID 27852

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test ltree                    ... ok

============== shutting down postmaster               ==============

============== removing temporary installation        ==============

 

=====================

 All 1 tests passed. 

=====================

 

 

另外一种测试时installcheck,和check不同的是,installcheck不需要初始化数据库,是在我们开启了数据库集群的情况下的测试。

同样的方法,我们可以发现它调用的是:

 

 

        $(pg_regress_installcheck) $(REGRESS_OPTS) $(REGRESS)

 

通过src/Makefile.global的定义:

 

 

pg_regress_installcheck = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --psqldir='$(PSQLDIR)' $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)

bindir := $(shell $(PG_CONFIG) --bindir)

 

以及

 

 

src/makefiles/pgxs.mk

PSQLDIR = $(bindir)

 

最终转换为:

 

 

../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql/bin' ltree

 

启动数据库后,就可以进行测试了。同样需要注意(PGPORT PGHOST PGDATABASE PGUSER等)环境变量。

 

 

postgres@digoal-> pg_ctl start

postgres@digoal-> pwd

/opt/soft_bak/postgresql-9.4.4/contrib/ltree

postgres@digoal-> ../../src/test/regress/pg_regress --inputdir=. --psqldir='/opt/pgsql/bin' ltree

(using postmaster on /data01/pg_root_1921, port 1921)

============== dropping database "regression"         ==============

DROP DATABASE

============== creating database "regression"         ==============

CREATE DATABASE

ALTER DATABASE

============== running regression test queries        ==============

test ltree                    ... ok

 

=====================

 All 1 tests passed. 

=====================

 

所以插件的回归测试配置也很简单,同样需要sql, expected目录,以及通过配置Makefile来指定需要回归测试的sql脚本。

 

[参考]

1. http://www.postgresql.org/docs/devel/static/regress-run.html

2. http://www.postgresql.org/docs/devel/static/regress-variant.html

各种Makefile

src/Makefile.global

src/Makefile

src/makefiles/pgxs.mk 

contrib/contrib-global.mk 

contrib/xx/Makefile

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值