Test-Framework

Dec 16, 2013
3 min read
May 31, 2023 18:15 EEST

Installation

To install it type:

emerge sys-devel/automake
emerge sys-devel/autoconf
emerge dev-libs/check

or
apt-get install autoconf automake check

Setting up with autoconf and automake

Create a directory for your project and create a file autogen.sh:

#!/bin/sh
if [ -n "$CHECK_DIR" ]; then
    aclocal -I $CHECK_DIR
else
    aclocal
fi
autoconf
autoheader
automake --add-missing

./configure "$@"

echo
echo "Now type 'make check' to compile."

Create the file Makefile.am:

INCLUDES=@CHECK_CFLAGS@

if HAVE_CHECK
TESTS=check_money
else
TESTS=
endif

noinst_PROGRAMS=$(TESTS)

lib_LIBRARIES= libmoney.a

libmoney_a_SOURCES= \
    money.h\
    money.c

check_money_SOURCES= \
	 money.h\
	 money.c\
	 check_money.c

check_money_LDADD= @CHECK_LIBS@

Now create the file configure.in:

dnl Process this file with autoconf to produce a configure script.
AC_INIT(money.h)
AM_INIT_AUTOMAKE(money,0.2)

dnl Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S

dnl This macro is defined in check.m4 and tests if check.h and libcheck.a
dnl can be found. It sets CHECK_CFLAGS and CHECK_LIBS accordingly.
dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
AM_PATH_CHECK(,[have_check="yes"],
	AC_MSG_WARN([Check not found; cannot run unit tests!])
	[have_check="no"])
AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")

dnl Checks for header files.
AM_CONFIG_HEADER(config.h)

dnl Checks for typedefs, structures, and compiler characteristics.

dnl Checks for library functions.

AC_OUTPUT(Makefile)

Create the programm itself

Create the file money.c:

#include <money.h>

Create the file money.h:

#ifndef MONEY_H
#define MONEY_H

#endif

Create the file check_money.c:

#include <check.h>
#include <stdlib.h>
#include "money.h"

START_TEST (test1)
{
}
END_TEST

int main(void)
{
   return 0;
}

Create the testroutines

Edit check_money.c:

#include <check.h>
#include <stdlib.h>
#include "money.h"

Money *five_dollars;
void setup(void)
{
   five_dollars=money_create(5, "USD");
}

void teardown(void)
{
   money_free(five_dollars);
}

START_TEST (test_create)
{
   fail_unless(money_amount(five_dollars)==5, 
          "Amount not set correctly on creation");
   fail_unless(strcmp(money_currency(five_dollars), "USD") == 0, 
          "Currency not set correctly on creation");
}
END_TEST

START_TEST (test_neg_create)
{
   Money *m=money_create(-1, "USD");
   fail_unless(m == NULL,
          "NULL should be returned on attempt to create with a negative amount");
}
END_TEST

START_TEST (test_zero_create)
{
   Money *m=money_create(0,"USD");
   fail_unless(money_amount(m)==0,"Zero is a valid amount of money");
}
END_TEST

Suite *money_suite(void)
{
   Suite *s=suite_create("Money");
   TCase *tc_core=tcase_create("Core");
   TCase *tc_limits=tcase_create("Limits");
   
   
   suite_add_tcase (s, tc_core);
   suite_add_tcase (s, tc_limits);
   

   tcase_add_test(tc_core, test_create);
   tcase_add_checked_fixture(tc_core, setup, teardown);
   
   tcase_add_test(tc_limits, test_neg_create);
   tcase_add_test(tc_limits, test_zero_create);
   
   return s;
}


int main(void)
{
   int nf;
   Suite *s=money_suite();
   SRunner *sr=srunner_create(s);

   srunner_set_log(sr, "test.log");
   
   srunner_run_all(sr, CK_NORMAL);
   nf=srunner_ntests_failed(sr);

   srunner_free(sr);
   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Create the functions

Edit money.h:

#ifndef MONEY_H
#define MONEY_H

typedef struct Money Money;

Money *money_create(int amount, char *currency);
int money_amount(Money *m);
char *money_currency(Money *m);
void money_free(Money *m);

#endif

Edit money.c:

#include <stdlib.h>
#include <money.h>

struct Money
{
      int amount;
      char *currency;
};

Money *money_create(int amount, char *currency) 
{ 
   if(amount <0)
      return NULL;
   Money *m = malloc(sizeof(Money));
   if(m == NULL)
      return NULL; 
   m->amount=amount;
   m->currency=currency;
   return m;
}
int money_amount(Money *m) 
{ 
  return m->amount; 
}
char *money_currency(Money *m) 
{ 
  return m->currency; 
}

void money_free(Money *m) 
{ 
   free(m);
}

Performing the checks

To prepare the compilation type:

./autogen.sh
./configure

To check if everything is fine and compile it type:

make check

Related Posts