简体   繁体   English

为我的 Postgres 对象编写基本的测试代码

[英]Writing basic test code for my Postgres objects

I'd like to build up some test code for various objects in my Postgres 11.5 database, and am wondering if there is a straightforward way to implement simple checks in straight SQL.我想为 Postgres 11.5 数据库中的各种对象构建一些测试代码,并且想知道是否有一种直接的方法可以在直接 SQL 中实现简单的检查。 As an example, I've got a simple domain that accepts any of three values, case-blind.例如,我有一个简单的域,它接受三个值中的任何一个,不区分大小写。 This is just one example I've picked because the test cases are finite and simple.这只是我选择的一个例子,因为测试用例是有限且简单的。

DROP DOMAIN IF EXISTS domains.test_outcome;

CREATE DOMAIN domains.test_outcome AS
    citext
    NOT NULL
    CONSTRAINT test_outcome_legal_values
        CHECK(
            VALUE IN ('pass','warning','fail')
     );

COMMENT ON DOMAIN domains.test_outcome IS
    'The test_outcome must be pass, warning, or fail, case-insensitive.';

Below are some simple test statements that exercise good and bad values:下面是一些简单的测试语句,它们使用了好的和坏的值:

-- Good values
select 'warning'::test_outcome;
select 'fail'::test_outcome;
select 'PASS'::test_outcome;
select 'WARNING'::test_outcome;
select 'FAIL'::test_outcome;

-- Bad values
select NULL::test_outcome;  
select ''::test_outcome;  
select 'foo'::test_outcome;

What I'd like to do, is get a single line for each case, and not blow up on an error.我想要做的是,为每个案例获取一行,而不是因为错误而崩溃。 I've tried using a DO block, and could use a PL/PgSQL function.我试过使用DO块,并且可以使用 PL/PgSQL 函数。 Here's the DO code I've tried:这是我尝试过的DO代码:

DO $TESTS$

BEGIN
-- Good values
    select 'warning'::test_outcome;
    select 'fail'::test_outcome;
    select 'PASS'::test_outcome;
    select 'WARNING'::test_outcome;
    select 'FAIL'::test_outcome;

-- Bad values
    select NULL::test_outcome;  
    select ''::test_outcome;  
    select 'foo'::test_outcome;

EXCEPTION WHEN OTHERS THEN
      RAISE NOTICE 'Error Name:%',  SQLERRM;
      RAISE NOTICE 'Error State:%', SQLSTATE;
END;
$TESTS$

What I get back are a couple of notices.我得到的是一些通知。 I can't tie those back to the specific statement, as far as I can tell, and I get nothing for success cases.据我所知,我无法将这些与具体声明联系起来,而且我对成功案例一无所知。

NOTICE:  Error Name:query has no destination for result data
NOTICE:  Error State:42601
DO
Command completed successfully. (Line 20)

I've seen that there are some unit testing frameworks for PG around, using languages we don't use.我已经看到有一些 PG 的单元测试框架,使用我们不使用的语言。 Is there any way to do simple tests like the ones above in straight SQL or PL/PgSQL?有没有办法在直接 SQL 或 PL/PgSQL 中进行像上面那样的简单测试?

There is nothing that I know of, but perhaps the following can provide a template for you.我一无所知,但也许以下内容可以为您提供模板。
I needed to modify your domain definition slightly removing the NOT NULL constraint in it.我需要稍微修改您的域定义,删除其中的 NOT NULL 约束。 The script below declares a working variable of the test_outcome .下面的脚本声明了test_outcome的工作变量。 However Postgres enforces the NOT NULL thus not allowing the declaration.但是 Postgres 强制执行 NOT NULL 从而不允许声明。 (A bug if you ask me, but ...). (如果你问我,这是一个错误,但是......)。 In this case not a great loss as NULL in not in the list of valid values at any rate.在这种情况下,无论如何都不会因为 NULL 不在有效值列表中而造成很大损失。

CREATE DOMAIN test_outcome AS
    citext
   -- NOT NULL
    CONSTRAINT test_outcome_legal_values
        CHECK(
            VALUE IN ('pass','warning','fail')
     );

The idea is to create an array of test items and iterate that array assigning each value to the the declared domain variable and capture any exception.这个想法是创建一个测试项数组并迭代该数组,将每个值分配给声明的域变量并捕获任何异常。 Note this part is within an inner begin...end block.请注意,这部分位于内部 begin...end 块内。 That prevents script termination when the errors are generated.这可以防止在生成错误时终止脚本。 For this type/level of testing I like to record successful test as well as failures so I have a raise notice for those as well.对于这种类型/级别的测试,我喜欢记录成功的测试和失败的测试,因此我也有关于这些测试的加薪通知。

do $$
declare 
   -- list items to be tested
   test_set text[] = $Q${warning,Fail,pass,WARNING,FAIL,null,'',foo}$Q$;

   -- define variable of data type being testes
   indx_val test_outcome;

   -- variable to contain text value 
   indx     text;
begin
    -- loop through test set, 
    -- Note the index variable must of same base type as array
    foreach indx in array test_set
    loop

        begin 
            indx_val = indx;  -- assign test 
            raise notice 'Testing: <%>. Successful.',indx;

            -- capture error in assign above
            exception when others then           
                raise notice 'Testing: <%>. Failed.',indx;
                raise notice '  *Error Name:%',  sqlerrm;
                raise notice '  *Error State:%', sqlstate;
        end ; 
    end loop;

exception when others then
      raise notice 'Error Name:%',  sqlerrm;
      raise notice 'Error State:%', sqlstate;
END;
$$;  

You should be able to adapt this general format other type definitions.您应该能够适应这种通用格式的其他类型定义。 Good Luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM