CeeFIT
The Framework for Integrated Test for C/C++
CeeFIT

Valid CSS!
©2006 Woldrich, Inc.
 
Using CeeFIT

Introduction

Java Fit works so nicely because it is so simple.  A large part of the design goals of CeeFIT was to enable developers and business users to have a similarly simple system for C++ program testing.  On the business user side, CeeFIT is almost identical in function to Java Fit, so from that standpoint CeeFIT wins there.  On the developer side, CeeFIT provides two mechanisms to develop and register Fixture classes with the system: the macro registration method and the manual registration method.  Which method you pick depends upon a couple things:

If you ...

  • don't need to put anything custom in your constructor or destructor because your members' constructors/destructors can manage themselves
  • don't mind calling macros that do crazy C++ things under-the-hood
  • don't need a header file to present your class declaration to other classes (you will likely need a header declaration for your Fixture if you plan to create other Fixtures that extend from it.)

then the macro method is for you, life is good!  Otherwise, you will need to manually write and register your fixture classes (which is no big deal, but not nearly as flashy or helpful as macros :-).

 

Macro Registration of Fixtures

CeeFIT macro registration will take your Fixture class fields and methods and register them automatically with the CeeFIT engine.  For the most part, macro registered Fixtures will only be useful for simple Fixture types like ColumnFixture.  Luckily, ColumnFixture covers many of the test cases you will likely encounter.  IMPORTANT NOTE:  the CeeFIT macros described below only work when called from .cpp files; do not try to put your Fixtures created with macros in header files, that will likely yield compiler or linker errors. 

Here is an example of a working ColumnFixture class file in the global namespace that uses macros (if your test code will reside in namespaces, use namespace-aware versions of the macros):

1 #include "ceefit.h"
2  

3

declare_fit_module(ExampleMultiply);
4  
5 begin_fit_fixture(MULTIPLY, CEEFIT::COLUMNFIXTURE, fitexample.Multiply)
6   fit_var(int, x);
7  
8   fit_var(int, y);
9  
10   fit_test(multiply, int)
11   {
12      return (x * y);
13   }
14 end_fit_fixture(MULTIPLY)
Figure 1 - multiply.cpp:  A CeeFIT ColumnFixture that has x, y, and multiply() columns.

Line descriptions:

1 - You must include the ceefit.h header to get all of the CeeFIT declarations, ceefit.h should be in the root of your CeeFIT installation and that folder should be added to your compiler's include path.
3 - declare_fit_module() is an optional macro you can add to your CeeFIT Fixture modules.  (The word module being used here refers to .cpp files.)  Many linkers will selectively exclude modules if other modules do not reference them, declare_fit_module() macro provides an anchor by which your Fixture's module can be referenced by another module.  Use the force_link_fit_module() macro in the module containing your main() function to create that reference and force the linker to link in your Fixture module.  Many linkers will NOT selectively exclude modules that cannot be directly referenced back to the main() module.  Your C++ environment may not require the use of these macros to link and execute CeeFIT fixtures.

Macro

Prototype

declare_fit_module(symbolicName)
Description Creates a variable synthesized from symbolicName that is used as an anchor point from which the linker can tie Fixture modules to the module containing your main() method.  declare_fit_module() should always appear in the global namespace.  A semi-colon is required after the declare_fit_module() macro.
Parameters
  • symbolicName : Can be any globally unique symbolic name.  Follows naming rules for any C++ symbol.
Macro

Prototype

force_link_fit_module(symbolicName)
Description Links a module containing the symbolicName to the current module.  force_link_fit_module() should always appear in the global namespace.   A semi-colon is required after the force_link_fit_module() macro.
Parameters
  • symbolicName : Can be any globally unique symbolic name.  Follows naming rules for any C++ symbol.

5 - The begin_fit_fixture() macro denotes the start of a CeeFIT Fixture class.  begin_fit_fixture() also defines a constructor and destructor for the Fixture class.  In this macro you specify what the name of your Fixture class will be, which base class your Fixture class will extend, and an alias for your classname.  This Fixture class is a simple multiplication test, and the base class for the multiply fixutre is CEEFIT::COLUMNFIXTURE.  The aliasName is saved as a string and allows for the CeeFIT engine to match HTML tables written for another language.  This Fixture class will match to a Fit HTML table named "MULTIPLY" and the alias allows it to match to a table named "fitexample.Multiply", which is the name of a corresponding Java Fixture class.

Macro

Prototype

begin_fit_fixture(className, extendsFrom, aliasName)
Description Begins a CeeFIT Fixture class.  begin_fit_fixture() must appear only in the global namespace.  A semi-colon is optional after the begin_fit_fixture() macro.  The default access rights established by begin_fit_fixture() is public.
Parameters
  • className : The name of your Fixture class.
  • extendsFrom : The fully qualified name of the Fixture class your class will extend from.
  • aliasName : An alias that your Fixture class can match to.

6, 8 - The fit_var() macro defines a named variable that is automatically registered with the CeeFIT engine to match against columns in the input HTML files.  These lines register int variables with the names x and y.

Macro

Prototype

fit_var(varType, varName)
Description Defines and registers a CeeFIT Fixture variable for the current Fixture class.  A semi-colon is required after the fit_var() macro.
Parameters
  • varType : The type of the member variable for your CeeFIT Fixture.
  • varName : The name of the member variable for your CeeFIT Fixture.  varName is case-sensitive and its spelling must match exactly to expected items in the input HTML tables.

10-13 - The fit_test() macro defines a named no-arg test method that is automatically registered with the CeeFIT engine to match against columns in the input HTML files.  This line registers a test method called multiply that returns an int that is compared against expected result data in the input HTML files.

Macro

Prototype

fit_test(testName, returnType)
Description Defines and registers a CeeFIT Fixture test method for the current Fixture class.  This macro must be followed by a C++ code block that returns an object of type returnType.  The function defined is a virtual function.
Parameters
  • testName : The name of the CeeFIT Fixture test method.  testName is case-sensitive and its spelling must match exactly to expected items in the input HTML tables.
  • returnType : The type of the object returned from your CeeFIT Fixture test method.

14 - The end_fit_fixture() macro closes off the end of your CeeFIT Fixture class.

Macro

Prototype

end_fit_fixture(className)
Description Finishes a CeeFIT Fixture class.  end_fit_fixture() must appear only in the global namespace.  A semi-colon is optional after the end_fit_fixture() macro.
Parameters
  • className : The name of your Fixture class, must match the name used in the corresponding begin_fit_fixture().

 

Namespace-Aware Macro Registrations

If you use namespaces in your C++ programs and wish for your Fixture classes to be namespaced as well, you may do so using the namespace-aware macros provided with CeeFIT.  Here is an example of the namespace-aware macros:

1 #include "ceefit.h"

2

 

3

declare_fit_module(FatDivide);
4  
5 using namespace CEEFIT;
6  
7 namespace CEEFAT
8 {
9   begin_namespaced_fit_fixture(CEEFAT, DIVIDE, COLUMNFIXTURE, fat.Divide)
10     fit_var(int, x);
11  
12     fit_var(int, y);
13  
14     fit_test(divide, int)
15     {
16       if(y == 0)
17       {
18         STRING message;
19         message += x;
20         message += "/";
21         message += y;
22         throw new DIVIDEBYZEROEXCEPTION(message);
23       }
24       return x/y;
25     }
26   end_namespaced_fit_fixture(CEEFAT, DIVIDE)
27 };
Figure 2 - divide.cpp:  A CeeFIT ColumnFixture in the CEEFAT namespace that has x, y, and divide() columns.

Line descriptions:

5 - You may use the using keyword to import all symbols in the CEEFIT namespace.  We do this here, and as a result, COLUMNFIXTURE does not need to be prefaced by "CEEFIT::" later on in the code.
7 - This is opens the CEEFAT namespace.  In Java Fit, the "fat" package contains some additional classes used in certifying Fit complies with the Fit Specification 1.1.  CeeFIT ships with a port of the fat package, and that code resides in the "CEEFAT" namespace.
9 - begin_namespaced_fit_fixture() macro is like begin_fit_fixture() except that the first parameter is the name of the namespace that the current fixture will be added to.  If the namespace the Fixture is being added to is more than one level deep, separate your namespace names with the scope resolution "::" operator.  (eg.  MYGAME::FITTESTS).  The name of the class is combined with the namespace and that forms the complete name which the CeeFIT engine can use to match the class with HTML input tables.  In the case of this Fixture, it will match to the strings "CEEFAT::DIVIDE" and the alias "fat.Divide".

Macro

Prototype

begin_namespaced_fit_fixture(namespaceName, className, extendsFrom, aliasName)
Description Begins a namespaced CeeFIT Fixture class.  begin_namespaced_fit_fixture() must appear in a namespace (other than global).  A semi-colon is optional after the begin_namespaced_fit_fixture() macro.
Parameters
  • namespaceName : The namespace your Fixture class is in. Do not end this name with a scope resolution operator "::".
  • className : The name of your Fixture class.
  • extendsFrom : The fully qualified name of the Fixture class your class will extend from.
  • aliasName : An alias that your Fixture class can match to.

16-24 - This CeeFIT test is all about testing integer division.  In order to avoid a processor fault due to div/0, we compare the y variable with 0 first.  If it is zero, we build an exception reason STRING variable and throw a DIVIDEBYZEROEXCEPTION back to the CeeFIT engine.  Otherwise, we return x/y.
26 - end_namespaced_fit_fixture() macro terminates your Fixture class just like the end_fit_fixture() does.  You must specify the namespace name and Fixture class name in this macro.

Macro

Prototype

end_namespaced_fit_fixture(namespaceName, className)
Description Finishes a namespaced CeeFIT Fixture class.  end_namespaced_fit_fixture() must appear in a namespace (other than global).  A semi-colon is optional after the end_namespaced_fit_fixture() macro.
Parameters
  • namespaceName : The namespace your Fixture class is in. Do not end this name with a scope resolution operator "::".
  • className : The name of your Fixture class, must match the name used in the corresponding begin_namespaced_fit_fixture().
27 - This brace closes off the CEEFAT namespace body.

 

Manual Registration of Fixtures

The manual registration of Fixtures achieves the same definition/registration of your Fixture classes similarly to the macro registration style.  On the plus side, you have more control over the features your Fixture class can sport and things generally look more C++-ish than with the macros.  On the minus side, it's generally takes more effort for you to get things working correctly.

Here is an example of a PrimitiveFixture-based Fixture class that could only be pulled off with the manual Fixture registration technique.  PrimitiveFixtures do not use reflection to match columns with member methods and variables.  Rather, with a class that extends PrimitiveFixture, you manually inspect the PARSE object passed to you and process it however you like.  PARSE is a value class that contains the parsed HTML tables which you can navigate to read and process elements.

In the case of the Table Fixture here, it is used as a tool.  It is very common when writing Fit tests to nest the construction and processing of Fixture classes.  The Table Fixture is a very simple demonstration of this type of containment: the rows of the table below the title row are parsed and run through the CeeFIT engine as another Fixture.

1 using namespace CEEFIT;
2  
3 namespace CEEFAT
4 {
5   class TABLE : public PRIMITIVEFIXTURE
6   {
7     public:
8       static PTR<PARSE> Table;
9  
10       inline ceefit_init_spec TABLE(void) {}
11       inline virtual ceefit_dtor_spec ~TABLE(void) {}
12  
13       virtual void ceefit_call_spec DoRows(PTR<PARSE>& rows);
14       static VALUE<PARSE> ceefit_call_spec Copy(PTR<PARSE>& tree);
15  
16       virtual void ceefit_call_spec ReleaseStatics(void);
17  
18     private:
19       ceefit_init_spec TABLE(const TABLE&);
20       TABLE& ceefit_init_spec operator=(const TABLE&);
21   };
22 };
Figure 3 - table.h:  A CeeFIT PrimitiveFixture in the CEEFAT namespace.


Line descriptions:

5 - This is the class declaration, where class TABLE extends from CEEFIT::PRIMITIVEFIXTURE.  Always extend from any Fixture base class with the "public" scope.
8- This is a static variable used by the TABLE class that keeps track of a copy of the rows following the title row.  This static variable is interesting in that it references a variable that was dynamically allocated from the CeeFIT heap.  In order to ensure that this field is deallocated before the program terminates, we add code later on that manages the memory for those statics.
10-11- It is your responsibility to define the default constructor and destructor for any FIXTURE's you manually register.  This is in contrast to the macro registration technique where the constructor and destructor are provided for you.

Calling Specification

Name

ceefit_init_spec
Description Your default constructor and copy constructor, destructor must be declared and defined with the ceefit_init_spec call spec, (if you want it to be cross-platform enough to compile with Borland C++ Builder or MSVC6.)

Calling Specification

Name

ceefit_dtor_spec
Description Your destructor must be declared and defined with the ceefit_dtor_spec call spec, (if you want it to be cross-platform enough to compile with Borland C++ Builder or MSVC6.)

13 - DoRows() is a Fixture base class function.  Overriding this method allows you to define the action taken when the CeeFIT engine goes to process all rows of the Fixture.

Calling Specification

Name

ceefit_call_spec
Description operator=() and any other methods in your class must be declared and defined with the ceefit_call_spec call spec, (if you want it to be cross-platform enough to compile with Borland C++ Builder or MSVC6.)  This rule holds for any functions in manual or macro-registered Fixtures.

14 - The static utiltiy Copy() method does a deep copy of the PARSE object passed, returning a pointer to the PARSE object in a VALUE<PARSE> object.
16 - ReleaseStatics() is a method you can override in your Fixture classes if you have static variables that need to have their memory released before the CeeFIT engine completes a call to CEEFIT::Run().  If you implement ReleaseStatics(), you must make sure to call the base class' ReleaseStatics() method in the body of your method so that its statics get released as well.  In your ReleaseStatics() method, make sure to set any pointers or PTR objects to null to eliminate the potential for double-frees.
19-20 - declare (but do not define) any standard functions that you do not need with private access rights.

The following code is the corresponding table.cpp file for table.h:

1 #include "ceefit.h"
2 #include "fat/Table.h"
3  
4 declare_fit_module(FatTable);
5
6 using namespace CEEFIT;
7  
8 namespace CEEFAT
9 {
10   PTR<PARSE> TABLE::Table(null);
11  
12   void ceefit_call_spec TABLE::DoRows(PTR<PARSE>& rows)
13   {
14     PTR<PARSE> nullParse(null);
15     STRING emptyString;
16
17     PTR<PARSE> rowCopy(Copy(rows));
18     TABLE::Table = new PARSE(STRING("table"), emptyString, rowCopy, nullParse);
19  
20     // evaluate the rest of the table like a runner
21     PTR<FIXTURE> temp(new FIXTURE());
22     temp->DoTables(TABLE::Table);
23   }
24  
25   VALUE<PARSE> ceefit_call_spec TABLE::Copy(PTR<PARSE>& tree)
26   {
27     if(tree == null)
28     {
29       return(VALUE<PARSE>(null));
30     }
31     else
32     {
33       PTR<PARSE> treeParts(Copy(tree->Parts));
34       PTR<PARSE> treeMore(Copy(tree->More));
35  
36       return(VALUE<PARSE>(new PARSE(tree->Tag, tree->Body, treeParts, treeMore)));
37     }
38   }
39  
40   void ceefit_call_spec TABLE::ReleaseStatics(void)
41   {
42     TABLE::Table = null;
43  
44     this->PRIMITIVEFIXTURE::ReleaseStatics();
45   }
46  
47   static REGISTERFIXTURECLASS< TABLE > FatTableFixtureRegistration("CEEFAT::TABLE",
48                                                                    "fat.Table");
49 };
Figure 4 - table.cpp:  A CeeFIT PrimitiveFixture definition in the CEEFAT namespace.

Line descriptions:

4 - We did not forget the declare_fit_module()/force_link_fit_module() in case the compiler/linker isn't clever enough to link in table.cpp as is.
10 - The definition of the static Table variable.
12-23 - The DoRows() method.  Builds a PARSE object by copying the remaining rows object and then performs a DoTables() on it so that it gets acted on as if it were a table.
25-38 - static Copy() method.  Recursively traverses and builds a copy of the passed PARSE object.
40-45 - The ReleaseStatics() method.  Just before CEEFIT::Run() returns, a temporary instance of every registered Fixture is created and ReleaseStatics() is invoked.  This ReleaseStatics() method null's the static Table variable and then calls the super class' ReleaseStatics() method.  By implementing ReleaseStatics(), we ensure that the memory for TABLE::Table is released before the end of the CeeFIT run.
47 - The static instance of the REGISTERFIXTURECLASS<T> class registers the class with the CeeFIT engine.  This line pulls the whole system together.  To register your Fixture class, make sure you create a static instance of REGISTERFIXTURECLASS<T> where T equals your Fixture class.

Manual Fixture Registration

Constructor

REGISTERFIXTURECLASS<T>(const char* fullClassName,
                        const char* aliasName)
Description Registers a Fixture class with the CeeFIT engine.  You should call this constructor from a static instance of REGISTERFIXTURECLASS<T>.
Template
Parameters
  • T : The Fixture class you wish to register with the CeeFIT engine.
Parameters
  • fullClassName : The fully qualified name of the class (including namespace) as it will show up in the input HTML tables.
  • aliasName : An alias name for your Fixture.

The following example Fixture shows how to manually register member methods and variables so that base classes like ColumnFixture or ActionFixture can use reflect on your Fixture's features to set its variables or call its methods.  The actual function of this Fixture is to serve as a data container for individual pieces of music that flow through the Music Example - one of the supplemental test suites that show off Fit's abilities.  Anywhere reflection is required in your classes, you will need to ultimately derive from FIXTURE so that functions like RegisterCeefitField() and RegisterCeefitTest() can safely be called.  Completely understanding this class and what its purpose is not required for this example - what is important is to see how the default constructor is used here to register fields and tests (member variables and methods) with the CeeFIT engine for this Fixture.

1 #include "tools/alloc.h"
2 #include "ceefit.h"
3 #include "eg/eg.h"
4
5 declare_fit_module(MusicClass);
6 using namespace CEEFIT;
7
8 namespace EG_MUSIC
9 {
10   const char* MUSIC::Status = "ready";
11
12   ceefit_init_spec MUSIC::MUSIC()
13   {
14     Size = 0L;
15     Seconds = 0;
16     TrackNumber = 0;
17     TrackCount = 0;
18     Year = 0;
19     Selected = false;
20
21     RegisterCeefitField(this, "title", Title);
22     RegisterCeefitField(this, "artist", Artist);
23     RegisterCeefitField(this, "album", Album);
24     RegisterCeefitField(this, "genre", Genre);
25     RegisterCeefitField(this, "size", Size);
26     RegisterCeefitField(this, "seconds", Seconds);
27     RegisterCeefitField(this, "trackNumber", TrackNumber);
28     RegisterCeefitField(this, "trackCount", TrackCount);
29     RegisterCeefitField(this, "year", Year);
30     RegisterCeefitField(this, "date", Date);
31     RegisterCeefitField(this, "selected", Selected);
32
33     RegisterCeefitTest(this, "track", &MUSIC::Track);
34     RegisterCeefitTest(this, "time", &MUSIC::Time);
35   }
36
37   ceefit_dtor_spec MUSIC::~MUSIC()
38   {
39   }
40
41   MUSIC& ceefit_call_spec MUSIC::operator=(const MUSIC& aMusic)
42   {
43     Title = aMusic.Title;
44     Artist = aMusic.Artist;
45     Album = aMusic.Album;
46     Genre = aMusic.Genre;
47     Size = aMusic.Size;
48     Seconds = aMusic.Seconds;
49     TrackNumber = aMusic.TrackNumber;
50     TrackCount = aMusic.TrackCount;
51     Year = aMusic.Year;
52     Date = aMusic.Date;
53     Selected = aMusic.Selected;
54
55     return(*this);
56   }
57
58   STRING ceefit_call_spec MUSIC::Track()
59   {
60     return(STRING() + TrackNumber + " of " + TrackCount);
61   }
62
63   double ceefit_call_spec MUSIC::Time()
64   {
65     double result = (Seconds / 0.6);
66     if(Seconds >= 0)
67     {
68       return(floor(result + 0.5) / 100.0);
69     }
70     else
71     {
72       return(ceil(result + 0.5) / 100.0);
73     }
74   }
75
76   int ceefit_call_spec MUSIC::GetHashCode(void) const
77   {
78     return(Title.GetHashCode());
79   }
80
81   bool ceefit_call_spec MUSIC::IsEqual(const MUSIC& aMusic) const
82   {
83     return(Title.IsEqual(aMusic.Title)
84            && Artist.IsEqual(aMusic.Artist)
85            && Album.IsEqual(aMusic.Album)
86            && Genre.IsEqual(aMusic.Genre)
87            && Size == aMusic.Size
88            && Seconds == aMusic.Seconds
89            && TrackNumber == aMusic.TrackNumber
90            && TrackCount == aMusic.TrackCount
91            && Year == aMusic.Year
92            && Date.IsEqual(aMusic.Date)
93            && Selected == aMusic.Selected);
94   }
95
96   STRING ceefit_call_spec MUSIC::ToString() const
97   {
98     if(Title.Length() == 0)
99     {
100       return Title;
101     }
102     else
103     {
104       return this->OBJECT::ToString();
105     }
106   }
107
108
109   // Factory //////////////////////////////////
110
111   VALUE ceefit_call_spec MUSIC::Parse(const STRING& string)
112   {
113     MUSIC* m = new MUSIC();
114
115     DYNARRAY parsedTokens;
116     Tokenize(parsedTokens, string, STRING("\t"));
117     int i = 0;
118     m->Title = parsedTokens[i++];
119     m->Artist = parsedTokens[i++];
120     m->Album = parsedTokens[i++];
121     m->Genre = parsedTokens[i++];
122     if(!swscanf(parsedTokens[i++].GetBuffer(), L"%li", &m->Size) ||
123       !swscanf(parsedTokens[i++].GetBuffer(), L"%i", &m->Seconds) ||
124       !swscanf(parsedTokens[i++].GetBuffer(), L"%i", &m->TrackNumber) ||
125       !swscanf(parsedTokens[i++].GetBuffer(), L"%i", &m->TrackCount) ||
126       !swscanf(parsedTokens[i++].GetBuffer(), L"%i", &m->Year))
127     {
128       throw new PARSEEXCEPTION("Parse exception in MUSIC::Parse");
129     }
130     m->Date.Parse(parsedTokens[i++]);
131
132     return VALUE(m);
133   }
134
135   STRING ceefit_call_spec MUSIC::Dump() const
136   {
137     STRING out;
138     STRING numberParts;
139     STRING dateString(Date.ToString());
140
141     SafeSprintf(numberParts, L"%li\t%i\t%i\t%i\t%i",
142                 Size, Seconds, TrackNumber, TrackCount, Year);
143
144     out += Title + "\t" + Artist + "\t" + Album + "\t" + Genre +
145            "\t" + numberParts + "\t" + dateString;
146
147     return(out);
148   }
149  
150   static REGISTERFIXTURECLASS< MUSIC > MusicRegistration("EG_MUSIC::MUSIC",
151                                                          "eg.music.Music");
152 };
Figure 5 - music.cpp:  The Music class from the MusicExample definition in the EG_MUSIC namespace.

 

Line descriptions:

12-35 - In manually registered fixtures, the constructor is responsible for initializing member variables and then registering with the CeeFIT engine any variables and tests that will be discovered via reflection later on.  Two methods are used to achieve this:  RegisterCeefitField() and RegisterCeefitTest()

Manual Fixture Registration

Function

template<class FIXTURETYPE, class FIELDTYPE>
  void RegisterCeefitField(FIXTURETYPE* fixture,
                           
const char* fieldName,
                           FIELDTYPE& actualField)
Description Registers a member variable by name and reference with the CeeFIT engine for a given Fixture.  You should only call this method from the constructor of your Fixture class.  Invoking this method on a given member variable allows that variable to be accessed via the pseudo-reflection API's provided by the CeeFIT engine.
Template
Parameters
  • FIXTURETYPE : The Fixture class your member variable being registered belongs to.
  • FIELDTYPE : The type of the member variable being registered.  This type must have a template specialization for FITFIELD<T> class where T equals FIELDTYPE.  That specialization must be defined in a header that is included in any modules invoking RegisterCeefitField() or the REGISTERFIXTURECLASS<T> constructor for the associated Fixture class.
Parameters
  • fixture : The Fixture containing member variable to be registered.
  • fieldName : A character string with the exact, case sensitive name of the field being registered as it should match to items in the input HTML tables.  Note, this string need not match the case nor spelling of actualField (but it should match exactly if you care about stuff like that.)
  • actualField : A reference to the actual member variable being registered within fixture.

 

Manual Fixture Registration

Function

template<class FIXTURETYPE, class RETURNTYPE>
  void RegisterCeefitTest(FIXTURETYPE* fixture,
         const char* testName,
         
RETURNTYPE (ceefit_call_spec FIXTURETYPE::*testFunc)(void))
Description Registers a no-arg pointer-to-method by name with the CeeFIT engine for a given Fixture.  You should only call this method from the constructor of your Fixture class.  Invoking this method on a given method allows that method to be called via the pseudo-reflection API's provided by the CeeFIT engine.
Template
Parameters
  • FIXTURETYPE : The Fixture class your method being registered belongs to.
  • RETURNTYPE : The type of the variable returned by testFunc.  This type must have a template specialization for FITFIELD<T> class where T equals RETURNTYPE.  That specialization must be defined in a header that is included in any modules invoking RegisterCeefitTest() or the REGISTERFIXTURECLASS<T> constructor for the associated Fixture class.
Parameters
  • fixture : The Fixture containing the method to be registered.
  • testName : A character string with the exact, case sensitive name of the method being registered as it should match to items in the input HTML tables.  Note, this string need not match the case nor spelling of testFunc (but it should match exactly if you care about stuff like that.)
  • testFunc : A pointer to the no-arg method being registered within fixture.

 

Manual Fixture Registration

Function

template<class FIXTURETYPE, class RETURNTYPE, class ARGTYPE>
  void RegisterCeefitTest(FIXTURETYPE* fixture,
         const char* testName,
         
RETURNTYPE (ceefit_call_spec FIXTURETYPE::*testFunc)(ARGTYPE))
Description Registers a one arg pointer-to-method by name with the CeeFIT engine for a given Fixture.  You should only call this method from the constructor of your Fixture class.  Invoking this method on a given method allows that method to be called via the pseudo-reflection API's provided by the CeeFIT engine.  One arg methods are used only by advanced Fixture types like RowFixture.  There is no macro equivalent for one arg method registration.
Template
Parameters
  • FIXTURETYPE : The Fixture class your method being registered belongs to.
  • RETURNTYPE : The type of the variable returned by testFunc.  This type must have a template specialization for FITFIELD<T> class where T equals RETURNTYPE.  That specialization must be defined in a header that is included in any modules invoking RegisterCeefitTest() or the REGISTERFIXTURECLASS<T> constructor for the associated Fixture class.
  • ARGTYPE : The type of the argument to testFunc.
Parameters
  • fixture : The Fixture containing the method to be registered.
  • testName : A character string with the exact, case sensitive name of the method being registered as it should match to items in the input HTML tables.  Note, this string need not match the case nor spelling of testFunc (but it should match exactly if you care about stuff like that.)
  • testFunc : A pointer to the one arg method being registered within fixture.

 

 
 
Prev: Installing CeeFIT | Cur: Using CeeFIT | Next: Advanced Topics
 

1