Beginner's steps with TDD
Jason Gorman has agreed to mentor me
in the subject of TDD (Test Driven Development). I plan to document my progress
as I learn the principles behind this philosophy.
TDD can be roughly outlined as follows:
Write a failing test for the desired functionality.
Write the smallest amount of code that can make that test pass.
Refactor you code, making sure your changes don’t break functionality (keep
running the tests)
As my first introduction to TDD Jason and I did some pair programming where I
implemented a simple Fibonacci function, this enabled me to see how the general
principle worked: “Test a little, program a little”, and see what sort of
obstacles I might come across, such as “What’s the next test going to be where
there is no linear progression to follow”.
I’ve given my self a quick crash course in git to document my progress, I can
commit every time I write a test or a piece of code. The history of the code
can be viewed using gitk filename
using a GUI or git log --follow --all -p
filename
[1].
I don’t have the commit history for the very first Fibonacci sequence exercise
I did, however I’ve got my third attempt at it (it’s pretty similar to the
first, I’ve just been trying to internalize the concepts I’ve met so far).
commit 9c764e57c26e43a87954fbc9026119530c2b6ecf
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:56:42 2013 +0000
Rename testLengthOf51 -> testLengthOfFiftyOne for consistency
diff --git a/fibonacci.py b/fibonacci.py
index b6d3197..dc28f8c 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -39,7 +39,7 @@ class TestFibonacciGenerator(unittest.TestCase):
def testLengthOfSeven(self):
self.assertRaises(ValueError, self.fibonacciGenerator, 7)
- def testLengthOf51(self):
+ def testLengthOfFiftyOne(self):
self.assertRaises(ValueError, self.fibonacciGenerator, 51)
if __name__ == '__main__':
commit b73e6566b457ae493195ab04d8baf2bf5cfaf1bf
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:56:13 2013 +0000
Code to pass testLengthOf51
diff --git a/fibonacci.py b/fibonacci.py
index d3df5a9..b6d3197 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -4,7 +4,7 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
- if (length < 8):
+ if (length < 8 or length > 50):
raise ValueError
fibonacciSequence = [0, 1]
@@ -39,5 +39,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testLengthOfSeven(self):
self.assertRaises(ValueError, self.fibonacciGenerator, 7)
+ def testLengthOf51(self):
+ self.assertRaises(ValueError, self.fibonacciGenerator, 51)
+
if __name__ == '__main__':
unittest.main()
commit 67062b240b5d25631fd8d87fc2aeb3ae5e9b983e
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:54:41 2013 +0000
Code to pass TestLengthOfSeven
diff --git a/fibonacci.py b/fibonacci.py
index fcd695d..d3df5a9 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -4,6 +4,9 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
+ if (length < 8):
+ raise ValueError
+
fibonacciSequence = [0, 1]
for i in range(2, length):
commit c313448c856360f009864e4c54d0fb25b47143ef
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:53:56 2013 +0000
Test for length of 7 (invalid)
diff --git a/fibonacci.py b/fibonacci.py
index 274d12b..fcd695d 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -33,5 +33,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testValidLength(self):
self.assertEquals(8, len(self.fibonacciGenerator(8)))
+ def testLengthOfSeven(self):
+ self.assertRaises(ValueError, self.fibonacciGenerator, 7)
+
if __name__ == '__main__':
unittest.main()
commit 0ad4ec5dd3a1df92fe40afb608f62ac7c8c52cda
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:50:05 2013 +0000
Changed testLength to testValidLength for clarity
diff --git a/fibonacci.py b/fibonacci.py
index 61f6f9a..274d12b 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -30,7 +30,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testSixthNumber(self):
self.assertEquals(5, self.fibonacciGenerator(8)[5])
- def testLength(self):
+ def testValidLength(self):
self.assertEquals(8, len(self.fibonacciGenerator(8)))
+
if __name__ == '__main__':
unittest.main()
commit f3c473f0fdd0d3e21f23efcf0916ea188a08f44c
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:49:13 2013 +0000
Test length of list
diff --git a/fibonacci.py b/fibonacci.py
index 783b800..61f6f9a 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -7,7 +7,7 @@ class TestFibonacciGenerator(unittest.TestCase):
fibonacciSequence = [0, 1]
for i in range(2, length):
- fibonacciSequence.append(fibonacciSequence[i-2] + fibonacciSequence[i-1])
+ fibonacciSequence.append(fibonacciSequence[i - 2] + fibonacciSequence[i - 1])
return fibonacciSequence
@@ -29,5 +29,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testSixthNumber(self):
self.assertEquals(5, self.fibonacciGenerator(8)[5])
+
+ def testLength(self):
+ self.assertEquals(8, len(self.fibonacciGenerator(8)))
if __name__ == '__main__':
unittest.main()
commit 1130cea31b30924f49fe49f3042da45a2825a460
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:47:05 2013 +0000
Test 6th number + code for that
diff --git a/fibonacci.py b/fibonacci.py
index f1b21d9..783b800 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -5,8 +5,10 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
fibonacciSequence = [0, 1]
+
for i in range(2, length):
- fibonacciSequence.append(i - 1)
+ fibonacciSequence.append(fibonacciSequence[i-2] + fibonacciSequence[i-1])
+
return fibonacciSequence
# TESTS
@@ -24,5 +26,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testFifthNumber(self):
self.assertEquals(3, self.fibonacciGenerator(8)[4])
+
+ def testSixthNumber(self):
+ self.assertEquals(5, self.fibonacciGenerator(8)[5])
if __name__ == '__main__':
unittest.main()
commit d0256181239d47d8d975eed0bfb4277fb7a78ae2
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:40:18 2013 +0000
Test fifth number, no code needed to pass
diff --git a/fibonacci.py b/fibonacci.py
index 3400d82..f1b21d9 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -22,5 +22,7 @@ class TestFibonacciGenerator(unittest.TestCase):
def testFourthNumber(self):
self.assertEquals(2, self.fibonacciGenerator(8)[3])
+ def testFifthNumber(self):
+ self.assertEquals(3, self.fibonacciGenerator(8)[4])
if __name__ == '__main__':
unittest.main()
commit 92b636a26292f1e78078652c039347bca2027321
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:36:11 2013 +0000
Test fourth number, no code needed to pass
diff --git a/fibonacci.py b/fibonacci.py
index c43b118..3400d82 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -19,5 +19,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testThirdNumber(self):
self.assertEquals(1, self.fibonacciGenerator(8)[2])
+ def testFourthNumber(self):
+ self.assertEquals(2, self.fibonacciGenerator(8)[3])
+
if __name__ == '__main__':
unittest.main()
commit 08b1e5edc66858f2205e16f32875706e06a128e6
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 17:35:02 2013 +0000
Code for third test
diff --git a/fibonacci.py b/fibonacci.py
index 28ed083..c43b118 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -4,8 +4,12 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
- return [0, 1]
+ fibonacciSequence = [0, 1]
+ for i in range(2, length):
+ fibonacciSequence.append(i - 1)
+ return fibonacciSequence
+ # TESTS
def testFirstNumber(self):
self.assertEquals(0, self.fibonacciGenerator(8)[0])
commit a5f3e527cdc205afeaf8df930534304a991091bd
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 14:59:51 2013 +0000
Add code for passing second test, test for third number
diff --git a/fibonacci.py b/fibonacci.py
index c9d28f3..28ed083 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -4,7 +4,7 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
- return [0]
+ return [0, 1]
def testFirstNumber(self):
self.assertEquals(0, self.fibonacciGenerator(8)[0])
@@ -12,6 +12,8 @@ class TestFibonacciGenerator(unittest.TestCase):
def testSecondNumber(self):
self.assertEquals(1, self.fibonacciGenerator(8)[1])
+ def testThirdNumber(self):
+ self.assertEquals(1, self.fibonacciGenerator(8)[2])
if __name__ == '__main__':
unittest.main()
commit f04d7ec901640e5771a4ae816f17fbfade9ee9af
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 14:58:04 2013 +0000
Code to pass first test, test for second number
diff --git a/fibonacci.py b/fibonacci.py
index 54fe5bf..c9d28f3 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -4,11 +4,14 @@ import unittest
class TestFibonacciGenerator(unittest.TestCase):
def fibonacciGenerator(self, length):
- return [None]
+ return [0]
def testFirstNumber(self):
self.assertEquals(0, self.fibonacciGenerator(8)[0])
+ def testSecondNumber(self):
+ self.assertEquals(1, self.fibonacciGenerator(8)[1])
+
if __name__ == '__main__':
unittest.main()
commit a6a83808fb900638706ccfdbbe922b36f5e27d4d
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 14:51:39 2013 +0000
Testing first fibonacci number, implemented fibonacciGenerator function
diff --git a/fibonacci.py b/fibonacci.py
index f4dfbd8..54fe5bf 100755
--- a/fibonacci.py
+++ b/fibonacci.py
@@ -1,7 +1,14 @@
#!/usr/bin/env python2
import unittest
+
class TestFibonacciGenerator(unittest.TestCase):
+ def fibonacciGenerator(self, length):
+ return [None]
+
+ def testFirstNumber(self):
+ self.assertEquals(0, self.fibonacciGenerator(8)[0])
+
if __name__ == '__main__':
unittest.main()
commit d8bbcd07a01cc3b84a006bb8546133604bed12ba
Author: Will Price <will.price94@gmail.com>
Date: Tue Jan 29 10:16:20 2013 +0000
Skeleton
diff --git a/fibonacci.py b/fibonacci.py
new file mode 100755
index 0000000..f4dfbd8
--- /dev/null
+++ b/fibonacci.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python2
+import unittest
+
+class TestFibonacciGenerator(unittest.TestCase):
+
+if __name__ == '__main__':
+ unittest.main()
You might disagree with my steps, or marvel at my crap commit messages; I’m just
getting started with the tools and methodologies so hopefully in 6 months time
I’ll be able to look back at this and correct all my mistakes.
I’ve been using tmux
to organise my work, vim
to edit it, git
to save
progress and watch
to continually test my code (this is very handy!). I’m
reasonably pleased with this workflow, it’s both simple and flexible.
[1] - ‘–follow’ handles renames, ‘–all’ shows commits on all branches, ‘-p’
shows the changes in patch form (otherwise you just get commit messages)