CppSpec
Behaviour driven development with C++

Example

In this example we define the behaviour of a stack. The implementation of the stack is shown below.

template<typename ElementType>
class Stack {
public:
	explicit Stack() : vector() {}

	void push(ElementType element) {vector.push_back(element);}
	
	void pop() {
		if(vector.empty()) {
			throw std::exception();
		}

		vector.pop_back();
	}
	
	ElementType top() {
		if(vector.empty()) {
			throw std::exception();
		}
		
		return vector.back();
	}	
	
	int count() const {return vector.size();}
	bool empty() const {return vector.empty();}
	
	bool operator==(const Stack& rhs) {
		return vector == rhs.vector;
	}
	
private:
	Stack(const Stack& rhs);
	Stack& operator =(const Stack& rhs);

private:
	std::vector vector;
};

The stack has several interesting states which should be tested, e.g. empty stack and stack containing elements.

Empty stack can be specified using the following specification:

class EmptyStackSpec : public CppSpec::Specification<Stack<int>, EmptyStackSpec> {
public:
	EmptyStackSpec() {
		REGISTER_BEHAVIOUR(EmptyStackSpec, poppingShouldRaiseException);
		REGISTER_BEHAVIOUR(EmptyStackSpec, backShouldRaiseException);
		REGISTER_BEHAVIOUR(EmptyStackSpec, stackIsEmpty);
		REGISTER_BEHAVIOUR(EmptyStackSpec, stackEqualsWithEmpty);
		REGISTER_BEHAVIOUR(EmptyStackSpec, countShouldBeZero);
	}
	
	void poppingShouldRaiseException() {
		specify(invoking(&Stack::pop).should.raise.exception());
	}
	
	void topShouldRaiseException() {
		specify(invoking(&Stack::top).should.raise.exception());		
	}

	void stackIsEmpty() {
		specify(should.be().empty());
	}
	
	void stackEqualsWithEmpty() {
		Stack anotherStack;
		specify(context, should.equal(anotherStack));
	}
	
	void countShouldBeZero() {
		specify(context().count(), should.equal(0));
	}
};
REGISTER_SPECIFICATION(EmptyStackSpec);

The specification is derived from CppSpec::Specification template class which is instantiated with context as an template argument. The context object is always accessible using Context& context() method.

REGISTER_BEHAVIOUR macro is used to register all the behaviours in the specification. REGISTER_SPECIFICATION is used to register all the specifications for the execution.

Other examples: