BDD extensions

944 views
Skip to first unread message

hubert

unread,
Oct 22, 2010, 3:24:17 PM10/22/10
to Google C++ Testing Framework
Hi Guys

I've been playing with some BDD extensions to GoogleTest that allow me
to write given-when-then tests. It all very simple - I've used
functions instead of subclasses so the fixtures don't work at the
moment - and will need tidying up. This is inspired by Cucumber et al
but avoids the cross-language issues and integrates better with
traditional unit testing. Anyone interested?

An example:

struct GivenFixture : testing::Test, BddState // multiple
inheritance keeps things apart nicely
{
};

class Calc {
public:
int add() { return x + y; }
void setX(int x) { this->x = x; }
void setY(int y) { this->y = y; }
private:
int x, y;
};

auto_ptr<Calc> calc;

GIVEN(GivenFixture, "A new calculator")
{
calc = auto_ptr<Calc>(new Calc);
}

GIVEN(GivenFixture, "foobar") {} // not used, just to check that
multiple GIVENs work

WHEN(GivenFixture, "I enter (\\d+) and (\\d+)")
{
calc->setX(atoi(args[1].c_str()));
calc->setY(atoi(args[2].c_str()));
}

THEN(GivenFixture, "The result is (\\d+)")
{
ASSERT_EQ(atoi(args[1].c_str()), calc->add());
}

TEST_F(GivenFixture, initialState) // test the BDD extensions
themselves
{
ASSERT_EQ(2, givens.size());
ASSERT_EQ(1, whens.size());
ASSERT_EQ(1, thens.size());
}

TEST_F(GivenFixture, addGiven)
{
given("a new calculator");
when("I enter 2 and 3");
then("The result is 5");
}

Zhanyong Wan (λx.x x)

unread,
Oct 22, 2010, 3:37:00 PM10/22/10
to hubert, Google C++ Testing Framework

Interesting.

I haven't done BDD myself, so I may be missing something obvious.
Could you explain the benefit of this over

int CalculateAdd(int x, int y) {
Calc calc;
calc.setX(x);
calc.setY(y);
return calc.add();
}

TEST(CalcTest, AddWorks) {
EXPECT_EQ(5, CalculateAdd(2, 3));
}

? Thanks,

--
Zhanyong

Keith Ray

unread,
Oct 23, 2010, 7:10:32 AM10/23/10
to Google C++ Testing Framework, hubert
Kevlin Henney (@KevlinHenney http://curbralan.com/ ) tweeted some
generally-accepted naming advice that I have paraphrased and expanded:

Rule 1: Name tests as propositions, not as functions/methods (and not
after functions/methods).

Testing strcat? here are some good names:

TEST(StrcatTests, TwoEmptyStringsShouldResultInAnEmptyString)
TEST(StrcatTests, OneEmptyOneNonEmptyShouldResultInNonemptyString)
TEST(StrcatTests, TwoNonEmptyStringsResultInCombinedString)

Rule 2: if you have to start names with 'test', start instead with 'testThat'
because it encourages propositional names.

TEST(StrcatTests, testThatTwoNonEmptyStringsResultInCombinedString)

Rule #3: if 'should' helps give you more intentional names use it,
otherwise drop the noise and use a more direct name.

TEST(StrcatTests, strcatNonEmptyStringsShouldResultInCombinedString)

Rule #4: watch out for truisms in test names, e.g., using "correct"
or "correctly" in a test name

DON'T DO: Test(StrcatTest, strcatTwoNonEmptyStringsCorrectly)

Rule #5: also treat the use of "can" in a test name with a little suspicion
(but not as much as "correct")

NOT GOOD: TEST(StrcatTests, strcatCanHandleTwoEmptyStrings)


2010/10/22 Zhanyong Wan (λx.x x) <w...@google.com>:

--
--
C. Keith Ray
 Web: http://industriallogic.com
 Twitter: @CKeithRay, @IndustrialLogic

Amplify Your Agility
Coaching | Training | Assessment | eLearning

Dr. Eck

unread,
Oct 28, 2010, 5:45:51 PM10/28/10
to Google C++ Testing Framework
I find this discussion of BDD interesting. I actually stumbled across
BDD before I started working seriously with TDD, so I began with the
advantage of understanding this helpful philosophy. For anyone who is
not familiar with BDD, please read this post by Dan North:
http://behaviour-driven.org/Introduction

That said, I see two ways of using BDD: first, as a method for
developers and second, as a means of communicating with customers. To
fully implement the latter, it would be necessary to have the tests
written as acceptance criteria for the project (executable
specifications). I'm afraid you can't get there with gtest because
there is still too much extraneous verbiage required by C++. But
perhaps you can get close enough for your customers if they are savvy.

Apart from that, I think implementing BDD for developers is more about
philosophy than syntax. Once you get it in your head that test naming
conventions are important, you are well on the way. For instance, a
really bad name for your first test would be "TestEmptyStrings".
However, "TwoEmptyInputStrings" might be sufficiently descriptive to
remind the developer of what was being tested a year later. Adding
"...ShouldResultIn..." makes things perfectly clear just by reading
the test name, but this information is made redundant by the ASSERT.
The optimal balance between DRY and test naming is up to you.

For me, at least, BDD boils down to Dan's point #6: "Expertise in TDD
begins to dawn at the point where the developer realizes that TDD is
about defining behavior rather than testing."

Best regards,
Steve Eckhardt
st...@eckop.com
Reply all
Reply to author
Forward
0 new messages