Bu Blogda Ara

19 Ağustos 2010 Perşembe

EclEmma Test Code Coverage Tool

I have been using TestNG test framework with Mockito Mock Framework on my Eclipse IDE. I strongly advise those of you who are using a similar set of tools for Unit Tests to have a look at Code coverage tool EclEmma. With EclEmma you can run your TestNG tests and see the test coverage to discover missing scenarios. It has other features as well http://www.eclemma.org/

11 Ağustos 2010 Çarşamba

switching Iphone to Android experience.

http://designbygravity.wordpress.com/2010/08/10/iphone-to-droid-x-lots-more-good-than-bad

13 Mayıs 2010 Perşembe

special computer glasses reduced my headaches!

Staring on my laptops or desktops screen without rest caused me a lot of headaches in my previous assignments. It has been 6 months I own a pair of Special computer glasses. The headache is gone for sure, I heavily recommend these glasses. Gunnar Optics

Usage Example of Boost Graph adjacency_list for Combining some Actions.

The below piece of code is just a quick sample reference code produced by me on Usage of Boosts Graph library (QT Console Application). The motivation is to combine together of actions together on a graph and proceed to next Action according to the current running Actions result.



// main.cpp

#include "qtcore/qcoreapplication"
#include "qtglobal"
#include "qstring"
#include "qlist"
#include "qdebug"

#include "boost/utility.hpp"
#include "boost/property_map.hpp"
#include "boost/graph/adjacency_list.hpp"


#include "Deneme1Class.h"
#include "Deneme2Class.h"
#include "Deneme3Class.h"


using namespace boost;


enum vertex_trobject_t{ vertex_trobject};
enum edge_retresult_t { edge_retresult };

namespace boost {
BOOST_INSTALL_PROPERTY(vertex, trobject);
BOOST_INSTALL_PROPERTY(edge, retresult);
}

typedef property VertexProperty;
typedef property EdgeProperty;
typedef adjacency_list TrActionGraph;
typedef property_map::type TrActionPropType;

typedef std::pair Edge;
typedef graph_traits::out_edge_iterator OutEdgeIterator;


// The below function is not exactly doing what I want it to do.
// create a tag for our new property
template
void travel(EdgeIter first, EdgeIter last, const TrActionGraph& G)
{
typedef typename property_map::const_type TrActionMap;
typedef typename boost::property_traits::value_type TrActionClass;
typedef typename property_map::const_type EdgeRetTypeMap;

// Access the propety acessor type for this graph
TrActionMap trmap = get(vertex_trobject, G);
EdgeRetTypeMap edgeMap = get(edge_retresult_t(), G);

TrActionClass src_trtype, targ_trtype;
src_trtype = boost::get(trmap, source(*first, G));
src_trtype->run();

while (first != last) {
src_trtype = boost::get(trmap, source(*first, G));
targ_trtype = boost::get(trmap, target(*first, G));
int retValProp = boost::get(edgeMap,*first);
if(src_trtype->getRetVal() == retValProp){
targ_trtype->run();
}
qDebug() <<>getTrId() << " is connected to "
<<>getTrId();
++first;
}

}

template
void travel2(VertexIter first, VertexIter last, const TrActionGraph& G)
{
typedef typename property_map::const_type TrActionMap;
typedef typename boost::property_traits::value_type TrActionClass;
typedef typename property_map::const_type EdgeRetTypeMap;

typedef std::pair OutEdgePair;

// Access the propety acessor type for this graph
TrActionMap trmap = get(vertex_trobject, G);
EdgeRetTypeMap edgeMap = get(edge_retresult_t(), G);

QList listOfStartingPoints;

// Get the list of starting points(vertices) of Graph store them in QList
while (first != last) {
if(in_degree(*first,G)==0){
listOfStartingPoints.push_back(first);
}
++first;
}

TrActionClass curActionObj;

QListIterator ourIter(listOfStartingPoints);
// Iterate all the starting vertexes of Graph
while(ourIter.hasNext()){
VertexIter curIter =ourIter.next();
// Do not iterate further if there is no more out edges That is to say the vertex in subject is the last vertex
while(out_degree(*curIter,G)!=0){
curActionObj = boost::get(trmap, *curIter);
curActionObj->run();
int actionResult = curActionObj->getRetVal();

// Get the Iterator of Out Edges
bool nextVerseFound = false;

OutEdgePair edgePair = out_edges(*curIter,G);

// Iterate through out edges to find the Edge Retval Property equals to Retval by Action Object
while(edgePair.first != edgePair.second){
int retValProp = boost::get(edgeMap,*edgePair.first);
if(retValProp == actionResult){
curIter = target(*edgePair.first, G);
nextVerseFound = true;
break;
}
++edgePair.first;
}
Q_ASSERT(nextVerseFound);
if(!nextVerseFound){
break; // should not continue any more in this situation if there are no further loops defined.
}

}
//
curActionObj = boost::get(trmap, *curIter);
curActionObj->run();
}

}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

// create a typedef for the Graph type
Deneme1Class tr1(0);
Deneme2Class tr2(1);
Deneme3Class tr3(2);
Deneme1Class tr4(3);
Deneme2Class tr5(4);
Deneme3Class tr6(5);
Deneme1Class tr7(6);
Deneme2Class tr8(7);
Deneme3Class tr9(8);
Deneme1Class tr10(9);
Deneme1Class tr11(10);
Deneme1Class tr12(11);

tr9.setNumberOfMaxRetries(1);

TrActionGraph graphOfTr(3);

Edge edge1(tr1.getTrId(),tr2.getTrId());
Edge edge2(tr1.getTrId(),tr3.getTrId());
Edge edge3(tr2.getTrId(),tr3.getTrId());
Edge edge4(tr3.getTrId(),tr4.getTrId());
Edge edge5(tr3.getTrId(),tr5.getTrId());
Edge edge6(tr4.getTrId(),tr6.getTrId());
Edge edge7(tr4.getTrId(),tr7.getTrId());
Edge edge8(tr6.getTrId(),tr8.getTrId());
Edge edge9(tr7.getTrId(),tr9.getTrId());
Edge edge10(tr7.getTrId(),tr10.getTrId());

Edge edge11(tr9.getTrId(),tr9.getTrId()); // Setting vertice loop to it self
Edge edge12(tr9.getTrId(),tr11.getTrId());
Edge edge13(tr9.getTrId(),tr12.getTrId());

add_edge(edge1.first, edge1.second,EdgeProperty(0), graphOfTr);
add_edge(edge2.first, edge2.second,EdgeProperty(1), graphOfTr);
add_edge(edge3.first, edge3.second,EdgeProperty(0), graphOfTr);
add_edge(edge4.first, edge4.second,EdgeProperty(0), graphOfTr);
add_edge(edge5.first, edge5.second,EdgeProperty(1), graphOfTr);
add_edge(edge6.first, edge6.second,EdgeProperty(0), graphOfTr);
add_edge(edge7.first, edge7.second,EdgeProperty(1), graphOfTr);
add_edge(edge8.first, edge8.second,EdgeProperty(0), graphOfTr);
add_edge(edge9.first, edge9.second,EdgeProperty(1), graphOfTr);
add_edge(edge10.first, edge10.second,EdgeProperty(0), graphOfTr);
add_edge(edge11.first, edge11.second,EdgeProperty(0), graphOfTr);
add_edge(edge12.first, edge12.second,EdgeProperty(2), graphOfTr);
add_edge(edge13.first, edge13.second,EdgeProperty(1), graphOfTr);

TrActionPropType trTypeMap = get(vertex_trobject_t(), graphOfTr);

boost::put(trTypeMap, tr1.getTrId(), &tr1);
boost::put(trTypeMap, tr2.getTrId(), &tr2);
boost::put(trTypeMap, tr3.getTrId(), &tr3);
boost::put(trTypeMap, tr4.getTrId(), &tr4);
boost::put(trTypeMap, tr5.getTrId(), &tr5);
boost::put(trTypeMap, tr6.getTrId(), &tr6);
boost::put(trTypeMap, tr7.getTrId(), &tr7);
boost::put(trTypeMap, tr8.getTrId(), &tr8);
boost::put(trTypeMap, tr9.getTrId(), &tr9);
boost::put(trTypeMap, tr10.getTrId(), &tr10);
boost::put(trTypeMap, tr11.getTrId(), &tr11);
boost::put(trTypeMap, tr12.getTrId(), &tr12);


//travel(edges(graphOfTr).first, edges(graphOfTr).second, graphOfTr);
travel2(vertices(graphOfTr).first, vertices(graphOfTr).second, graphOfTr);

return a.exec();
}
// end of main.cpp

// IDenemeInterface.h
#pragma once

#include

class IDenemeInterface
{
public:
IDenemeInterface();
virtual ~IDenemeInterface();

virtual void run()= 0;
virtual int getRetVal()= 0;
virtual int getTrId()= 0;
virtual QString getTrName()=0;

inline void setNumberOfMaxRetries(int retryCount){m_MaxRetryCount = retryCount;};
inline int getNumberOfMaxRetries()const{return m_MaxRetryCount;};

protected:
// Static property
int m_MaxRetryCount;

// Run Time property
int m_RetVal;
int m_CurrentRetryCount;

};

// endof IDenemeInterface.h

// IDenemeInterface.cpp

#include "IDenemeInterface.h"

IDenemeInterface::IDenemeInterface(): m_MaxRetryCount(0), m_CurrentRetryCount(0)
{
}

IDenemeInterface::~IDenemeInterface()
{
}

// end of IDenemeInterface.cpp

// Deneme1Class.h

#pragma once
#include "idenemeinterface.h"

class Deneme1Class :
public IDenemeInterface
{
public:
Deneme1Class(int trid);
virtual ~Deneme1Class(void);

void run();
int getRetVal();
int getTrId();
QString getTrName();

private:

int m_trid;
QString m_trname;
};

// endof Deneme1Class.h

// Deneme1Class.cpp
#include

#include "Deneme1Class.h"

Deneme1Class::Deneme1Class(int trid):m_trid(trid), m_trname("Deneme1 Tr")
{
}

Deneme1Class::~Deneme1Class(void)
{
}

void Deneme1Class::run(){
qDebug() << "Now at Deneme1Class run at obj id:" <<>
m_RetVal = 1;
}

int Deneme1Class::getRetVal(){
return m_RetVal;
}

int Deneme1Class::getTrId(){
return m_trid;
}

QString Deneme1Class::getTrName(){
return m_trname;
}

// endof Deneme1Class.cpp

// Deneme2Class.h
#pragma once
#include "idenemeinterface.h"

class Deneme2Class :
public IDenemeInterface
{
public:
Deneme2Class(int trid);
virtual ~Deneme2Class(void);

void run();
int getRetVal();
int getTrId();
QString getTrName();

private:
int m_trid;
QString m_trname;
};

// endof Deneme2Class.h

// Deneme2Class.cpp
#include

#include "Deneme2Class.h"

Deneme2Class::Deneme2Class(int trid):m_trid(trid), m_trname("Deneme2 Tr")
{
}

Deneme2Class::~Deneme2Class(void)
{
}

void Deneme2Class::run(){
qDebug() << "Now at Deneme2Class run at obj id:" <<>
m_RetVal = 0;

}

int Deneme2Class::getRetVal(){
return m_RetVal;
}


int Deneme2Class::getTrId(){
return m_trid;
}
QString Deneme2Class::getTrName(){
return m_trname;
}

// endof Deneme2Class.cpp

// Deneme3Class.h
#pragma once
#include "idenemeinterface.h"

class Deneme3Class :
public IDenemeInterface
{
public:
Deneme3Class(int trid);
virtual ~Deneme3Class(void);

void run();
int getRetVal();
int getTrId();
QString getTrName();


private:
int m_trid;
QString m_trname;
};



// endof Deneme3Class.h

// Deneme3Class.cpp

#include

#include "Deneme3Class.h"

Deneme3Class::Deneme3Class(int trid):m_trid(trid), m_trname("Deneme3 Tr")
{
}

Deneme3Class::~Deneme3Class()
{
}

void Deneme3Class::run(){
if(m_CurrentRetryCount++ > m_MaxRetryCount){
// no need to run anymore
m_RetVal = 1;
}else{
qDebug() << "Now at Deneme3Class run at obj id:" <<>
m_RetVal = 0;
}
}

int Deneme3Class::getRetVal(){
return m_RetVal;
}

int Deneme3Class::getTrId(){
return m_trid;
}

QString Deneme3Class::getTrName(){
return m_trname;
}


// endof Deneme3Class.cpp

30 Mart 2010 Salı

Praise to googletest and googlemock Unit Test frameworks.

Below text is not reducted for grammer.

Rationale:

In todays Software Development efforts if you are developing a long term software project it is essential that you give HIGH importance to Test Driven Development (TDD) approach. I cannot think of any Software Engineer that can develop and maintain the modules that he is responsible without writing white-box tests such as Unit and Integration Tests.

Software Engineers who resists to TDD approach are complaining mainly about tight software schedules and yet they dont really know the value of re-running tests before commiting changes to modules that they are responsible for.

Imagine in a tight schedule environment you are forced to add a new feature to the functionality you have implemented before. How would you be confident about the new implementation without re-testing the old functionality and make sure that nothing has broken. Etc...

Anyway I will mention about how googletest and googlemock eased my TDD approaches. Before meeting these testing frameworks I was using cppunit and my Fake Object implementations.

Drawbacks and struggles of cppunit

- You have to declare your test functions in .h implement them in .cpp and register them to the framework.

- I do not know of any mock framework that goes well with this test framework.

Drawbacks and struggles of Fake Object approach.

- I had to implement fake classes that were implementing some interfaces that real objects have implemented.

- I had to implement function switches in order to set some expectations before running my test code.

- I was ignoring to test positive test cases since implementation of the fake objects were becoming to complex for me. Because, I had to fill in all the structures required in my impementation such as when returning a structure from with in the function or as output argument of the function. So I was not implementing my Fake Objects to handle the positive cases and I was leaving this to the my Integration Tests.

- Because of my above approach my TDD was as following: First I was writing Integration Tests as I was developing, and finally I was writing Unit Tests to test negative cases at the end.


Why googletest and googlemock?

After all my time consuming TDD approaches I was looking for a better solution. When I first reserved some time for testing Googles Test Frameworks, I have observed the below benefits in order to decide contiuning developing with them.

- Google Test framework Test Functions require no declaration in header file, and neither require registeration of those functions.

- The console output legend is easy to understand with coloured texts etc..

- The Google Mock framework is just simply precompilation of expectations so I don't have to implement any Fake classes. You just declare the MOCK macros of your member functions that you are goint to mock. Below is an example

class MockWifiServiceApi : public WifiServiceImplementor{
public:
MockWifiServiceApi(ServiceManipulationInterfaceSharedPtr serviceApi):WifiServiceImplementor(serviceApi){};

MOCK_METHOD3(startService, ServiceReturnCodes(const QString& serviceName,
int timeOut,
bool * isStarted));
MOCK_METHOD3(stopService, ServiceReturnCodes(const QString& serviceName,
int timeOut,
bool * isStopped));
MOCK_METHOD2(isServiceExists, ServiceReturnCodes(const QString& serviceName,
bool * exists));
MOCK_METHOD2(isServiceRunning, ServiceReturnCodes(const QString& serviceName,
bool * running));
MOCK_METHOD1(locateService, ServiceReturnCodes(QString * serviceName));


};

- They also provide phyton scripts in order you to generate above header declaration automatically. Which is very nice.

- You can mock output arguments of a function in a handy way. And also provide you enough tricks for diffucult mocking problems such as arguments that dont have copy constructor or assignment operator defined.

- Finally it is very easy to learn and have a very good online wiki source.

Conclusion:

Googles Test Frameworks increased my productivity and helped me very much on enhancing the quality of my codes. Thanks to the Google Team for their significant contribution on open source development.







29 Mart 2010 Pazartesi

Hello world.