Howto integrate pgTAP and C++ / catch2 unit tests

38 views
Skip to first unread message

Martin Melchert

unread,
Jan 4, 2020, 1:33:57 PM1/4/20
to pgTAP Users
Hi to all pgtap user,

first of all:
this is great tool and helps a lot - many many  thanks to all developers working on it and make this tool open source.

My all day tool for unit tests is catch2. Most of my software is written in c/c++ and catch2 fits perfectly into my tool chain.

For reg Test of the SQL part i discover pgTAP - but how to integrate?
I found nothing on google that fits into the tool chain or my needs.


The database layer is connected via soci, but that is only a detail you can adopt to your favorite interface.

We need a header file for the test macros.

catch2/pgtap.hpp

#ifndef CATCH2_PGTAP_H
#define CATCH2_PGTAP_H

#include <external/catch2/catch.hpp>
#include <external/soci/include/soci/postgresql/soci-postgresql.h>
#include <external/soci/include/soci/soci.h>

// -----------------------------------------------------------------
// ------ some usefull TAP test macros -----------------------------
// -----------------------------------------------------------------

// ------ all tests inside transaction ... with NO commit ----------

// clang-format off
#define PGTAP_SETUP_TR(con_string)                                 \
  std::string connection_string = con_string;                      \
                                                                   \
  soci::session   sql(soci::postgresqlconnection_string);        \
  soci::indicator i1;                                              \
  std::string     TAP;                                             \
                                                                   \
  soci::transaction tr(sql);                                       \
  {                                                                \
    sql << "select * from no_plan()"soci::into(TAP, i1)

#define PGTAP_CLEANUP_TR                                           \
    sql << "SELECT * from finish(false)";                          \
  }

// ------ all tests without ----------------------------------------
#define PGTAP_SETUP(con_string)                                    \
  std::string connection_string = con_string;                      \
                                                                   \
  soci::session   sql(soci::postgresqlconnection_string);        \
  soci::indicator i1;                                              \
  std::string     TAP;                                             \
                                                                   \
  sql << "select * from no_plan()"soci::into(TAP, i1)

#define PGTAP_CLEANUP                                              \
  sql << "SELECT * from finish(false)"

// ------ test definition ------------------------------------------
#define PGTAP_TEST(test_sql)                                       \
  sql << test_sql, soci::into(TAP, i1);                            \
  INFO(TAP);                                                       \
  CHECK(TAP.find("ok"== 0)

// cla ng-format on

#endif



And the test units looks like this:

TEST_CASE("pgTAP/1""[DB][TAP]")
{
  const static std::string con_string = "user=test password=test host=localhost port=5432 dbname=test";
  
  PGTAP_SETUP_TR(con_string); // use the setup WITH transaction

  PGTAP_TEST("SELECT * FROM check_test( is(1, 1), true, 'is(1, 1)', '', '' )");
  PGTAP_TEST("SELECT * FROM check_test( is('x'::text, 'xy'::text), true, 'is(''x'', ''x'')', '', '' )"); // here is an error - only for demo of the output!
  PGTAP_TEST("SELECT * FROM check_test( is(1.1, 1.10), true, 'is(1.1, 1.10)', '', '' )");

  PGTAP_CLEANUP_TR(false); // cleanup with rollback - false: no exceptions
}



and here is the output:

-------------------------------------------------------------------------------
pgTAP/1
-------------------------------------------------------------------------------
../cpp/projects/core/kce_base/test/test_db_model.cpp:4
...............................................................................

../cpp/projects/core/kce_base/test/test_db_model.cpp:11: FAILED:
  CHECK( TAP.find("ok") == 0 )
with expansion:
  4 == 0
with messages:
  ok 1 - is(1, 1) should pass
  not ok 4 - is('x', 'x') should pass
  # Failed test 4: "is('x', 'x') should pass"
  #         have: false
  #         want: true

===============================================================================
test cases: 1 | 1 failed
assertions: 3 | 2 passed | 1 failed


This macro set is not perfect but works for me - so  I hope it helps

cheers

David E. Wheeler

unread,
Jan 7, 2020, 10:50:05 AM1/7/20
to Martin Melchert, pgTAP Users
On Jan 4, 2020, at 10:33, Martin Melchert <m.mel...@mm-software-consulting.de> wrote:

> This macro set is not perfect but works for me - so I hope it helps

Nice, thanks for sharing!

David

signature.asc
Reply all
Reply to author
Forward
0 new messages