Mecanismul Template TDD
Mecanismul Template TDD
TDD.
POO- Curs 11
Polimorfism probleme
Test.cpp
#include "Integer.h"
#include "Person.h"
#include "Array.h"
#include <iostream>
using namespace std;
void print(Array& a){
for(int i=0;i<a.length();i++)
cout<<a.getElem(i)->toString()<<" ";
cout<<endl;
}
int main(){
Array a(4);
a.add(new Integer(3));
a.add(new Integer(4));
a.add(new Integer(5));
a.add(new Person("Adriana"));
Person* p= (Person*)a.getElem(0);
cout<<p->toString()<<endl;
return 0;
}
Se compileaza????
DA.
In afara controlului compilatorului
Abordarea template ar identifica o astfel de eroare.
Test.cpp
#include "Integer.h"
#include "Person.h"
#include "Array.h"
#include <iostream>
using namespace std;
void print(Array& a){
for(int i=0;i<a.length();i++)
cout<<a.getElem(i)->toString()<<" ";
cout<<endl;
}
int main(){
Array a(4);
a.add(new Integer(3));
a.add(new Integer(4));
a.add(new Integer(5));
a.add(new Person("Adriana"));
Person* p= (Person*)a.getElem(0);
cout<<typeid(p).name()<<" "<<p->toString()<<endl;
Integer* i=(Integer*)a.getElem(3);
cout<<typeid(i).name()<<" "<<i-
>toString()<<endl;
Integer x;
Integer j=*i;
//Integer j=*(Integer*)a.getElem(0);
Integer s=x+j;
cout<<"Suma numerelor "<<j.toString()<<"
si "<<x.toString()<<" este
"<<s.toString()<<endl;
system("pause");
return 0;
}
RTTI (RunTime Type Identification)
Genericitate in diferite limbaje
C void*
Java + Smalltalk mostenire + polimorfism (o singura
clasa de baza Object, IE, TElem, etc)
2004 Java introduce generics
C++ nu are o ierarhie derivata dintr-o singura clasa de
baza
Unele biblioteci pot fi cumparate de la diversi furnizori
probabilitatea ca toate clasele sa fie derivate din aceeasi
clasa de baza scazuta
Polimorfism si Genericitate
Shape
<<interface>>
Circle
Square
Mostenire multipla
Cum am putea adauga
Shape-uri in Container?
Container
<<interface>>
Object
<<interface>>
Polimorfism si Genericitate
Shape
<<interface>>
Circle Square
Container
<<interface>>
Object
<<interface>>
OShape
OCircle
OSquare
Codul???
Greu de inteles, intretinut, etc
Solutia cea mai potrivita utilizarea template-urilor (Adapter/ wrapper
design pattern)
Design patterns = sabloane de
proiectare
Design Patterns: Elements of Reusable Object-Oriented
Software - 1994
Gang of Four (GoF )- Erich Gamma, Richard Helm, Ralph Johnson
and John Vlissides
Sabloane-clasificare:
Creationale instantierea claselor: Abstract Factory, Builder,
Factory Method, Prototype, Singleton
Structurale compunerea claselor si obiectelor: Adapter, Bridge,
Composite, Decorator, Faade, Flyweight, Proxy
Comportamentale: Chain of responsibility ,Command Interpreter,
Iterator, Mediator, Memento, Observer, State, Strategy,
Template method, Visitor
Sablonul Adapter
Translateaza o interfata a unei clase intr-o interfata compatibila
Permite unor obiecte care in mod normal nu ar putea sa coopereze
datorita interfetelor incompatibile sa colaboreze, furnizand clientilor
interfata proprie, in timp ce lucreaza cu interfata originala
Adaptorul transforma apelurile metodelor din interfata sa in apeluri
ale metodelor din interfata originala
De obieci, codul necesar este redus
Reutilizarea codului
Mostenirea si compozitia reutilizarea codului obiect
Mecanismul template reutilizarea codului sursa
Containerele standard C++ si algoritmii sunt dezvoltate
folosind exclusiv mecanismul template
Template = mecanism de creare a unor tipuri generice
de date
Solutia template
Containerul nu mai retine o clasa de baza generica (Object, IE,
TElem, etc), ci un parametru nespecificat
La utilizarea template-ului, parametrul este substituit de compilator
Mecanismul template implementeaza conceptul de tip parametrizat
= familie de tipuri relationate
Vector parametrizat = vector<int>, vector<char> ,
vector<Student>, vector <vector<int>>, etc
Ce poate fi template?
Functii
Clase
Membri
Functii template
Maximul a 2 numere
inline int max (int a, int b) {return a>b?a:b;}
inline long max (long a, long b) {return a>b?a:b;}
inline int max (int a, int b) {return a>b?a:b;}
inline long max(long a, long b) {return a>b?a:b;}
inline double max(double a , double b) {return a>b?a:b;}
overloading
Cod redundant
Functiile template
template <class T> inline T max(const T& a, const T& b) {return
a>b?a:b;}
Folosit pentru a
declara un template
Argumentul template-ului, tipul argumentului template-ului
Procesul de generare a unei functii concrete dintr-o functie template =
instantiere
int z=max<int>(3,7);
double d=max<double>(3.5, 4.9);
T=Student
T=Masina
Operatorul > supraincarcat !!!
Deductia tipului/specializarea
templateului
int i=3, j=4;
int z =max(i,j);
Compilatorul deduce min<int>(i,j) daca
ambele argumente au acelasi tip
double j=2.5;
int i=3;
max(i,j);
no matching function for call to `maxim (int &, double &)'
double j=2.5;
int i=3;
max<double>(i,j);
solutia
char* a=ana;
char* b=maria;
max(a,b);
Adrese!!!
template <> const char* maxim<const char*>(const char*
const& a, const char* const& b) {
return (strcmp(a,b)<0)?b:a;
}
Specializarea template-ului
Apel: max<>(a,b);
Functii template
#ifndef INTEGER_H
#define INTEGER_H
#include<iostream>
using namespace std;
class Integer{
private:
int i;
public:
Integer(int n=0):i(n){}
bool operator<(const Integer&v)const{
return i<v.i;
}
bool operator>(const Integer& v)const{
return i>v.i;
}
friend ostream& operator<<(ostream& os, Integer& i){
return os<<i.i<<endl;
}
~Integer(){}
};
#endif
#include<iostream>
using namespace std;
#include "Integer.h"
template <class T> inline T maxim(T a, T b){
return a>b?a:b;
}
int main(){
cout<< maxim<int>(2,5)<<endl;
cout<<maxim<double>(3.4, 8.9)<<endl;
cout<<maxim<Integer>(Integer(4), Integer(7));
return 0;
}
Clase template
Structura unei clase template, incluzand functii membre si date
statice:
template <class T> class A{
void f();
static T x;
};
template <class T> void A<T>::f(){}
template <class T> T A<T>::x=0;
Nume
clasa
Tip de
data
Declaratia
template
Tip
returnat
T reprezinta tipul argumentului template-ului si este
legat la acel tip in momentul instantierii
Instantierea unei clase template
A<int> a; (T=int)
Legarea argumentului template-ului si generarea clasei concrete =
instantiere
Template= schelet/macro/framework
La adaugarea unui tip specific acestui schelet clasa concreta C++
Argumentele template-ului pot fi si expresii constante:
template <int N> class A{}
A<-37> a;
Util cand se doreste transmiterea unei dimensiuni la un template
Clasa template Vector
Tipul elementelor parametru template
Capacitatea parametru template
template <class T, int N> class Vector {};
Vector<int, 100> v;
Valoare implicita
instantierea
Vector
-elem[*]: T
-dim: int
<<create>>-Vector()
+set(pos: int, val: T): void
+get(pos: int): T
<<CppOperator>>+[](: int): T
+add(: T): void
+size(): int
+remove(pos: int): T
T : class
CAP = 10
Clasa template Vector
#ifndef VECTOR_H
#define VECTOR_H
template <class T, int CAP=10> class Vector{
T elem[CAP];
int dim;
public:
Vector();
void set(int pos, T val);
T get(int pos) const;
void add(T);
int size();
T remove(int pos);
};
template<class T, int CAP> Vector<T,
CAP>::Vector(){dim=0;}
template<class T, int CAP> void
Vector<T,CAP>::set(int pos, T val){
elem[pos]=val;
}
template<class T, int CAP> T Vector<T, CAP>::get(int
pos) const{
return elem[pos];
}
template<class T, int CAP> void Vector<T,CAP>::add(T
a) {
elem[dim++]=a;
}
template<class T, int CAP> int Vector<T,CAP>::size(){
return dim;
}
template<class T, int CAP> T
Vector<T,CAP>::remove(int pos){
T aux = elem[pos];
elem[pos]=elem[--dim];
return aux;
}
#endif
Test
#include "Vector.h"
#include <iostream>
#include <conio.h>
using namespace std;
template <typename T, int CAP>
void read ( Vector<T, CAP>& v){
int n;
cout<<"Dati nr de elem :";
cin>>n;
T e;
for(int i=0;i<n;i++)
{cin>>e;
v.add(e);
}
}
template <typename T, int CAP>
void print (Vector<T,CAP> t) {
for (int i=0;i<t.size();i++)
cout<<t.get(i)<<" ";
cout<<endl;
}
int main(){
Vector<double> a;
read<double>(a);
print<double>(a);
Vector<int, 20> b;
read<int>(b);
print<int>(b);
// Vector<long,-40> c;
return 0;
}
Valid pana la instantierea
templateului
Test Vector
#include "Integer.h"
#include "Rational.h"
#include "Vector.h"
#include <iostream>
#include <typeinfo>
using namespace std;
template <class T> void print(Vector<T>& a){
for(int i=0;i<a.size();i++)
cout<<a.getElem(i)<<" ";
cout<<endl;
}
int main(){
Vector<Integer> a;
a.add(Integer(3));
a.add(Integer(4));
a.add(Integer(5));
a.add(Rational(2,7));
system("pause");
return 0;
}
La COMPILARE
Fisiere header
Atat declaratiile cat si definitiile unui template vor fi puse intr-un fisier
header
Regula generala pentru fisiere header: dont put anything that
allocates storage!
Template compilatorul nu va aloca spatiu in acel moment, ci doar
in momentul in care i se spune sa o faca (la instantiere)
Argumente ale template-ului
Template <class T> class A {};
Tipul argumentelor (T):
Void:
template <class T> class A{T* elem; };
A<void> a;
Argumente netipizate (expresii constante)
template <class T, int n> class A{
T elem[n];
};
A<float,100> b;
Cunoscut la compilare - evita alocarea dinamica a memorie
Argumente ale template-ului
Adresa unor obiecte externe
template <char* cp> class A{};
char c;
A<&c> a;
Adresa unei functii
template<void (*fp)(int)>class A{};
void f(int){}
A<f> a;
SirOrdonat
OrdSeq
-elem: T[*]
-n: Integer
+<<create>>OrdSeq()
+insert(e: T)
+dim(): Integer
+get(pos: Integer)
+<<destroy>>~OrdSeq()
T
int (*fc)(T,T)
CAP:int=10
SirOrdonat
#ifndef ORD_SEQ_H
#define ORD_SEQ_H
#include <iostream>
using namespace std;
template <class T, int (*cmpFun)(T,T), int CAP=10>
class OrdSeq{
T elem[CAP];
int n;
public:
OrdSeq(){n=0;}
void insert(T inf){
if(n==0) {elem[n++]=inf;return;}
if(cmpFun(elem[n-1],inf)){
elem[n++]=inf; return;
}
int p=0;
while((!cmpFun(inf,elem[p]))&&(p<n))
p++;
for(int j=n;j>p;j--) elem[j]=elem[j-1];
elem[p]=inf;
n++;
}
int dim(){return n;}
T get(int i){return elem[i];}
};
#endif
#include "OrdSeq.h"
#include <iostream>
using namespace std;
template <class T>int cresc(T a, T b){
return a<b;}
template <class T> int descresc(T a, T b){
return a>b;}
template <class T, int(*cmpFun)(T,T), int N> void
print(OrdSeq<T, cmpFun, N> o){
for(int i=0;i<o.dim();i++)
cout<<o.get(i)<<" ";cout<<endl;
}
int main(){
OrdSeq<int,descresc<int>,50> a;
a.insert(5);
a.insert(3);
a.insert(4);
print<int,descresc>(a);
OrdSeq<double, cresc <double>> b;
b.insert(3.4);
b.insert(4.5);
print<double,cresc>(b);
return 0;
}
Argumente ale templateului
TemplateTemplate.cpp
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
using namespace std;
template <class T> class Array{
enum{CAP=10};
T* elem;
int cap;
int dim;
public:
Array(){
dim=0;
cap=CAP;
elem=new T[CAP];
}
void push_back (const T& e){
if (dim==cap) {
T* aux = new T[2*cap];
cap*=2;
for(int i=0;i<dim;i++)
aux[i]=elem[i];
delete [] elem;
elem=aux;
}
elem[dim++]=e;
}
T* begin() { return elem;}
T* end() {return elem+dim;}
~Array() {delete [] elem;}
};
template <class T, template <class> class Seq> class
Collection{
Seq<T> s;
public:
void append(const T& e){s.push_back(e);}
T* begin(){return s.begin();}
T* end(){return s.end();}
};
#endif
Test.cpp
#include "TemplateTemplate.cpp"
int main(){
Collection <int, Array> c;
c.append(2);
c.append(3);
int* p = c.begin();
while(p!=c.end()){
cout<<*p++<<" ";
}
return 0;
}
Alte templateuri
Argument template
Clase template inner
Multime
-elem: T[*]
-n: integer
<<create>>-Multime()
<<destroy>>-Multime()
<<create>>-Multime(: Multime)
<<CppOperator>>+=(: Multime): Multime
<<CppOperator>>++(: Multime): Multime
<<CppOperator>>+-(: Multime): Multime
<<CppOperator>>+*(: Multime): Multime
<<CppOperator>>++=(: T): Multime
<<CppOperator>>+-=(: T): Multime
+dim(): integer
+apartine(: T): integer
+getIterator(): iterator
T : class
CAP = 10
iterator
+crt: Integer
+iterator(: Multime)
<<CppOperator>>+operator++()
<<CppOperator>>+operator--()
<<CppOperator>>+operator+=(: Integer)
<<CppOperator>>+operator-=(: Integer)
<<CppOperator>>+operator(): T
<<inner>>
Multime.h
#ifndef MULT_H
#define MULT_H
#include <iostream>
using namespace std;
template <class T, int CAP=10> class Multime{
private:
T elem[CAP];
int n;
public:
Multime();
~Multime();
Multime(const Multime&);
Multime& operator=(const Multime&);
Multime operator+(const Multime&) const;
Multime operator-(const Multime&) const;
Multime operator*(const Multime&) const;
Multime& operator+=(const T&);
Multime& operator -=(const T&);
int dim();
int apartine(const T&) const;
class iterator;
friend class iterator;
class iterator{
Multime& m;
int crt;
public:
iterator (Multime& n):m(n){crt=0;};
void operator++(){++crt;}
void operator--(){--crt;}
T operator()(){return m.elem[crt];}
int valid(){return ((crt>=0)&&(crt<m.n));};
iterator& operator+=(int i){crt+=i;return *this;}
iterator& operator-=(int i){crt-=i; return *this;}
};
iterator getIterator();
};
#endif
Multime.cpp
#include "MULTT.H"
template <class T, int CAP> Multime<T,CAP>:: Multime(){
n=0;
}
template <class T, int CAP> Multime<T,CAP>:: ~Multime(){
}
template <class T,int CAP> Multime<T,CAP>::Multime(const
Multime<T,CAP>& m){
n=m.n;
for(int i=0;i<m.n;i++)
elem[i]=m.elem[i];
}
template <class T,int CAP > Multime<T,CAP>
Multime<T,CAP>::operator+(const Multime<T,CAP>& m) const{
Multime<T,CAP> r(*this);
for(int i=0;i<m.n;i++)
if(r.apartine(m.elem[i])==0)
r+=m.elem[i];
return r;
}
template <class T,int CAP> Multime<T, CAP> Multime<T, CAP>::operator-
(const Multime<T, CAP>& m) const{
Multime <T, CAP> dif;
for(int i=0;i<n;i++)
if(m.apartine(elem[i])==0) dif+=elem[i];
return dif;
}
template <class T,int CAP> Multime<T,CAP>
Multime<T,CAP>::operator*(const Multime<T,CAP>& m) const{
Multime<T,CAP> i;
for(int j=0;j<n;j++)
if(m.apartine(elem[j])) i+=elem[j];
return i;
}
template <class T, int CAP> Multime<T, CAP>& Multime<T,
CAP>::operator+=(const T& e){
if (!apartine(e)) elem[n++]=e;
return *this;
}
template <class T, int CAP> Multime<T, CAP>& Multime<T,
CAP>::operator-=(const T& e){
for(int i=0;i<n;i++)
if(elem[i]==e){
for(int j=i;j<n-1;j++)
elem[j]=elem[j+1];
n--;
}
return *this;
}
template <class T, int CAP> int Multime<T, CAP>::apartine(const T& e)
const{
for(int i=0;i<n;i++)
if(elem[i]==e) return 1;
return 0;
}
template <class T, int CAP> Multime<T, CAP>&
Multime<T,CAP>::operator=(const Multime<T, CAP>& m){
if (this==&m){}
else{
n=m.n;
for(int i=0;i<n;i++)
elem[i]=m.elem[i];
}
return *this;
}
template <class T,int CAP> int Multime<T, CAP>::dim(){
return n;}
template <class T, int CAP> Multime<T,CAP>::iterator
Multime<T,CAP>::getIterator() {
Multime<T,CAP>::iterator it(*this); return it;
}
Test.cpp
#include "MULTT.cpp"
#include <iostream>
using namespace std;
template <class T> void citMult(Multime<T>& a){
T el;
cin>>el;
while(el!=0){
a+=el;
cin>>el;
}
}
template <class T, int CAP> void
tipMult(Multime<T,CAP> a){
Multime<T,CAP>::iterator it=a.getIterator();
while(it.valid()){
cout<<it()<<" ";
++it;
}
cout<<endl;
}
template <class T,int CAP> void tipMult(Multime<T,CAP> a,
int step){
Multime<T,CAP>::iterator it=a.getIterator();
while(it.valid()){
cout<<it()<<" ";
it+=step;
}
cout<<endl;
}
int main(){
Multime<int> m;
citMult<int>(m);
tipMult<int>(m);
tipMult<int>(m,2);
return 0;
}
Argumente ale template-ului
Ce NU poate fi argument al template-ului:
Expresii constante de tip flotant
Adrese ale unor vectori
Adrese ale unor membri nestatici ai unor clase
Tipuri locale
Adrese ale unor obiecte locale
Clase template echivalente
Doua clase template se refera la aceeasi clasa daca:
Numele templateului e identic
Sunt in acelasi domeniu de vizibilitate
Argumentele lor au valori identice
template <class T, int n> class A{};
typedef short* pShort;
A<short*, 100> a1;
A<pShort, 100> a2;
Acelasi tip
Template si interfete
IStiva
+push(: T): void
+pop(): T
+empty(): bool
+peek(): T
<<destroy>>-IStiva()
T : class
StivaS
-elem: T[*]
-top: Integer
<<create>>+StivaS()
<<destroy>>+~Stiva()
StivaD
<<create>>+StivaD()
<<destroy>>+~StivaD()
Nod
-info: T
-next: Nod
<<create>>+Nod(: T, : Nod)
<<create>>+Nod(: T)
<<destroy>>+~Nod()
-top
<<inner>>
Stiva
IStiva.h
#ifndef ISTIVA_H
#define ISTIVA_H
template <class T> class IStiva{
public:
virtual void push(const T&)=0;
virtual T pop()=0;
virtual bool empty()const=0;
virtual T& peek()const=0;
virtual ~IStiva(){}
};
#endif
StivaS.H
#ifndef STIVAS_H
#define STIVA_S
#include "IStiva.h"
template <class T, int CAP=10> class StivaS: public
IStiva<T> {
T elem[CAP];
int top;
public:
StivaS(){top=0;}
StivaS(const StivaS& s){
for(int i=0;i<s.top;i++)
elem[i]=s.elem[i];
top=s.top;
}
void push(const T& e){elem[top++]=e;}
T pop(){return elem[--top];}
T& peek()const{return elem[top-1];}
bool empty()const{return top==0;}
~StivaS(){}
};
#endif
Stiva
StivaD.cpp
#ifndef STIVAD_H
#define STIVA_D
#include "IStiva.h"
template <class T> class StivaD:public IStiva<T>{
class Nod{
T info;
Nod* next;
public:
Nod(const T& e, Nod* n):info(e),next(n){}
Nod(const T& e):info(e), next(0){};
~Nod(){};
template <class T> friend class StivaD;
}*top;
public:
StivaD(){top=0;}
void push(const T& e){
top=new Nod(e,top);
}
T pop(){
Nod* aux=top;
T e=aux->info;
top=top->next;
delete aux;
return e;
}
T& peek()const{
return top->info;
}
bool empty()const{
return (top==0);
}
~StivaD(){
while(top){
Nod* a=top;
top=top->next;
delete a;
a=top;
}
}
};
#endif;
Test.cpp
#include "StivaS.cpp"
#include "StivaD.cpp"
#include <iostream>
using namespace std;
int main(){
IStiva<int>* s= new StivaD<int>;
s->push(2);
s->push(5);
while(!s->empty()){
cout<<s->pop()<<" ";
cout<<endl;
}
return 0;
}
Test Driven Development (TDD)
Metoda de dezvoltare a softului bazat pe iteratii
Cicluri de dezvoltare foarte scurte:
Programatorul scrie teste automate care esueaza initial
defineste o imbunatatire dezirabila a unei functionalitati
scrie cod pentru a trece testul
Incurajeaza proiectarea simpla si inspira incredere
Instrumente pentru C++:
Visual Assert
CPPUnit
WinUnit
API-uri Visual Assert pentru C
CFIX_ASSERT verifica orice tip de expresie care se evalueaza la true sau
false
CFIX_ASSERT( a == 1 );
CFIX_ASSERT( !"This will always fail" );
CFIX_ASSERT_OK
CFIX_ASSERT_SUCCEEDED
CFIX_ASSERT_FAILED
CFIX_ASSERT_HRESULT
CFIX_ASSERT_STATUS
CFIX_ASSERT_MESSAGE
CFIX_ASSERT_EQUALS_DWORD, CFIX_ASSERT_EQUALS_ULONG
CFIX_FAIL
CFIX_INCONCLUSIVE un test nu e relevant esuare
CFIX_INCONCLUSIVE( L"This test case cannot be run on WOW64" );
CFIX_INCONCLUSIVE( L"This test case requires admin privileges" );
CFIX_LOG pentru a scrie in loguri diverse informatii
CFIX_LOG( L"A simple log message" );
CFIX_LOG( L"Value is %x, Last error was: %d", foo, GetLastError() );
CFIXCC_ASSERT_EQUALS
compararea pe baza operatorului ==
Pentru valori flotante se accepta o deviatie de 10 unitati pe ultima pozitie
class SomeClass {
private:
int value;
public:
bool operator == ( const SomeClass& other ) const
{ return this->value == other.value; } ...
};
Teste cu succes:
CFIXCC_ASSERT_EQUALS( SomeClass( 1 ), SomeClass( 1 ) );
CFIXCC_ASSERT_EQUALS( L"test", L"test" );
CFIXCC_ASSERT_EQUALS( 1.9999999f, 2.0f ); .
Teste care esueaza:
SomeClass* a = new SomeClass( 1 );
SomeClass* b = new SomeClass( 1 );
CFIXCC_ASSERT_EQUALS( a, b );
CFIXCC_ASSERT_EQUALS( L"test", L"" );
Valorile egale, pointerii nu
Visual Assert API pt C++
CFIXCC_ASSERT_EQUALS_MESSAGE
Similar lui CFIXCC_ASSERT_EQUALS
Valoare asteptata si cea actuala sunt vizibile in raport
CFIXCC_ASSERT_EQUALS_MESSAGE( 2.0f, myValue, "Compar %f cu 2.0", myValue );
Visual Assert API pt C++
Visual Assert API pt C++
CFIXCC_ASSERT_NOT_EQUALS
Comparatia pe baza operatorului !=
Pointerii se compara pe baza adreselor, exceptie char* care sunt
convertite la tipul string
CFIXCC_ASSERT_NOT_EQUALS( 1, 2 );
CFIXCC_ASSERT_NOT_EQUALS( L"test", L"" );
CFIXCC_ASSERT_NOT_EQUALS_MESSAGE
CFIXCC_ASSERT_NOT_EQUALS_MESSAGE( 2.0f, FloatValue,
Verificam ca %f nu e egal cu 2.0", FloatValue );
Visual Assert API pt C++
CFIXCC_ASSERT_LESS[_OR_EQUAL]
CFIXCC_ASSERT_LESS( 1, 2 );
CFIXCC_ASSERT_LESS( L"a", L"b" );
CFIXCC_ASSERT_LESS_OR_EQUAL( -1, 0 );
CFIXCC_ASSERT_LESS_OR_EQUAL( -1, -1 );
CFIXCC_ASSERT_LESS[_OR_EQUAL]_MESSAGE
CFIXCC_ASSERT_LESS_OR_EQUAL_MESSAGE( 2.0f, FloatValue,
"Checking that %f is smaller than or equal to 2.0", FloatValue );
Visual Assert API pt C++
CFIXCC_ASSERT_GREATER[_OR_EQUAL]
CFIXCC_ASSERT_GREATER( 3, 2 );
CFIXCC_ASSERT_GREATER( L"c", L"b" );
CFIXCC_ASSERT_GREATER_OR_EQUAL( 1, -1 );
CFIXCC_ASSERT_GREATER_OR_EQUAL( -1, -1 );
CFIXCC_ASSERT_GREATER[_OR_EQUAL]_MESSAGE
CFIXCC_ASSERT_GREATER_OR_EQUAL_MESSAGE( 2.0f,
FloatValue, "Checking that %f is greater than or equal to 2.0",
FloatValue );
Construirea unei suite de teste
TestFixture clasa de baza din care trebuie derivate toate clasele
pentru testare
Implementarea testelor se face adaugand metode cu nume diverse
la clasa de teste
Pentru initializarea datelor membre ale clasei derivate se pot
suprascrie metodele Before and After se apeleaza inainte si dupa
fiecare metoda din clasa de test
Pentru initializarea resurselor globale se pot folosi metodele SetUp
si TearDown ruleaza o singura data pe test
Declaratia clasei TestFixture
namespace cfixcc {
class TestFixture {
public:
TestFixture();
virtual ~TestFixture();
virtual void Before();
virtual void After();
static void SetUp();
static void TearDown();
};
}
Construirea unei suite de teste
Pentru fiecare clasa trebuie furnizata constructia
CFIXCC_BEGIN_CLASS/ CFIXCC_END_CLASS
CFIXCC_METHOD folosita pentru a adauga o metoda
de test la suita de teste
CFIXCC_METHOD(< metoda_de_test> )
O metoda de test are signatura void TestMethod();
Exemplu
#include <cfixcc.h>
class SimpleFixture : public cfixcc::TestFixture {
public:
void Method01() { ... }
void Method02() { ... }
};
CFIXCC_BEGIN_CLASS( SimpleFixture )
CFIXCC_METHOD( Method01 )
CFIXCC_METHOD( Method02 )
CFIXCC_END_CLASS()
Unit testing Integer
#include <cfixcc.h>
#include "Integer.h"
class IntegerFixture : public cfixcc::TestFixture
{
private:
Integer x;
public:
void Test()
{
CFIX_INCONCLUSIVE(__TEXT("Not implemented"));
}
void TestCopyConstructor(){
Integer a(2);
Integer b(a);
CFIXCC_ASSERT_EQUALS(a,b);
CFIXCC_ASSERT_NOT_EQUALS(b,Integer(5));
}
void TestOperatorPlusUnar(){
Integer a(6);
Integer x=+a;
CFIXCC_ASSERT_EQUALS(a,x);
CFIXCC_ASSERT_NOT_EQUALS(a,Integer(-3));
}
void TestOperatorMinusUnar(){
Integer a(-3);
Integer b=-a;
CFIXCC_ASSERT_EQUALS(b, Integer(3));
}
void TestOperatorPlusBinar(){
Integer y(3);
Integer suma=y+x;
CFIXCC_ASSERT_EQUALS(suma, Integer(3));
Integer z(5);
suma=y+z;
Integer exp(8);
CFIXCC_ASSERT_EQUALS(suma, exp);
CFIXCC_ASSERT_EQUALS_MESSAGE( exp,
suma, "Compar 8 cu ", suma );
}
void TestOperatorEgal(){
Integer z;
CFIX_ASSERT(x==z);
CFIX_LOG( L"Test egalitate" );
//CFIX_ASSERT(x==Integer(4));
}
};
CFIXCC_BEGIN_CLASS(IntegerFixture)
//CFIXCC_METHOD(Test)
CFIXCC_METHOD(TestCopyConstructor)
CFIXCC_METHOD(TestOperatorPlusUnar)
CFIXCC_METHOD(TestOperatorMinusUnar)
CFIXCC_METHOD(TestOperatorPlusBinar)
CFIXCC_METHOD(TestOperatorEgal)
CFIXCC_END_CLASS()