To develop a software based on “Test Driven Development” one should follow the following steps:
1 2 3 4 |
1)Write enough failing Test Code (include compile time and run time failures) 2)Write Production code to pass the failing tests. 3)Refactor the production code and verify the same with existing test. 4)Go to step 1 |
so let say we want to develop a binary search tree, here I’m using Google Test.
Step 1, Write enough failing Test Code
so the first step would be something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class testingTree: public ::testing::Test { protected: testingTree(){} ~testingTree(){} void SetUp(){} void TearDown(){} }; TEST_F(testingTree,makeTree) { std::shared_ptr<Tree> tree=makeTree(); EXPECT_NE(tree.get(),nullptr); } int main(int argc, char ** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } |
Step 2, Write Production code to pass the failing tests.
The code from first step will fail during compilation, so the next step is to add the production code such that we can compile and pass the test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Tree { public: std::array<std::shared_ptr<Tree>,2 > leaves; /* tree->leaves[0] left node tree->leaves[1] right node */ double data; }; std::shared_ptr<Tree> makeTree(double data) { return nullptr; } |
Now this will give us a test failure:
1 2 3 4 5 6 7 8 9 10 11 |
Expected: (tree) != (nullptr), actual: NULL vs (nullptr) [ FAILED ] testingTree.makeTree (0 ms) [----------] 1 test from testingTree (1 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (1 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] testingTree.makeTree 1 FAILED TEST |
and by adding more production code:
1 2 3 4 5 6 |
std::shared_ptr<Tree> makeTree(double data) { std::shared_ptr<Tree> tree(new Tree(data)); tree->data=data; return tree; } |
this will pass the test.
Step 3, Refactor the production code
step 3 is refactoring, by doing refactoring we can clean our code to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Tree { public: Tree(double data):data(data){} std::array<std::shared_ptr<Tree>,2 > leaves; /* tree->leaves[0] left node tree->leaves[1] right node */ double data; }; std::shared_ptr<Tree> makeTree(double data) { std::shared_ptr<Tree> tree(new Tree(data)); return tree; } |
Now we have to jump step1 again, add more test and continue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
class Tree { public: Tree(double data):data(data){} std::array<std::shared_ptr<Tree>,2 > leaves; /* tree->leaves[0] left node tree->leaves[1] right node */ double data; }; std::shared_ptr<Tree> makeTree(double data) { std::shared_ptr<Tree> tree(new Tree(data)); return tree; } void insertNode(std::shared_ptr<Tree> tree, double data) { while(1) { if(data>tree->data) { if(tree->leaves[1] ==nullptr) { tree->leaves[1]=makeTree(data); break; } else { tree=tree->leaves[1]; continue; } } else if(data<tree->data) { if(tree->leaves[0]==nullptr) { tree->leaves[0]=makeTree(data); break; } else { tree=tree->leaves[0]; continue; } } else { std::cout<<"no duplicate" <<std::endl; } } } void DFS(std::shared_ptr<Tree> rootNode) { std::cout<<rootNode->data <<std::endl; for(auto n:rootNode->leaves) { if(n!=nullptr) DFS(n); } } class testingTree: public ::testing::Test { protected: testingTree(){} ~testingTree(){} void SetUp(){} void TearDown(){} }; TEST_F(testingTree,makeTree) { std::shared_ptr<Tree> tree=makeTree(-1); EXPECT_NE(tree.get(),nullptr); } TEST_F(testingTree,traverseTree) { int value=5; std::shared_ptr<Tree> tree=makeTree(value); /* 5 / \ 3 7 / \ / 4 1 6 */ insertNode(tree,3); insertNode(tree,7); insertNode(tree,4); insertNode(tree,1); insertNode(tree,6); DFS(tree); } int main(int argc, char ** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } |