<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Wyatt Baldwin &#187; bdd</title>
	<atom:link href="http://wyattbaldwin.com/tag/bdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://wyattbaldwin.com</link>
	<description></description>
	<lastBuildDate>Wed, 11 Jan 2012 16:28:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Fun With Python BDD</title>
		<link>http://wyattbaldwin.com/2007/04/25/fun-with-python-bdd/</link>
		<comments>http://wyattbaldwin.com/2007/04/25/fun-with-python-bdd/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 17:59:01 +0000</pubDate>
		<dc:creator>Wyatt</dc:creator>
				<category><![CDATA[planet python]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://wyattbaldwin.com/2007/04/25/fun-with-python-bdd/</guid>
		<description><![CDATA[I was testing my algorithm/data structures chops by implementing a Linked List from scratch using no reference material (not very difficult, I know), and I must say that using BDD was incredibly helpful. I’m calling it “BDD” instead of “TDD” &#8230; <a href="http://wyattbaldwin.com/2007/04/25/fun-with-python-bdd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was testing my algorithm/data structures chops by implementing a Linked List from scratch using no reference material (not very difficult, I know), and I must say that using <span class="caps">BDD</span> was incredibly helpful. I’m calling it “BDD” instead of “TDD” just because the test class names describe a context and the method names in the test classes are behavior-oriented, inspired by the style found on the <a href="http://rspec.rubyforge.org/">RSpec site</a>.</p>
<p>I didn’t write the tests/specs up front like you’re “supposed” to. Instead, I thought about what I was trying to do, came up with an initial idea for the implementation, started writing code, and then added a test to make sure I was on the right track. This worked out pretty well. I also used the tests during refactoring. Writing the tests first might have worked out better, but I can’t say for sure.</p>
<p>Now, for some real fun, implement a linked list based on <em>only</em> the test code below.</p>
<pre style="font-size: 4px">
class LinkedList(object):
    def __init__(self, *values):
        self._size = 0
        if values:
            for v in values:
                self.add(v)
        else:
            self.head = self.tail = None

    def is_empty(self):
        return len(self) == 0

    def add(self, val):
        node = Node(val)
        if self.is_empty():
            self.head = node
        else:
            self.tail.next = node
        self.tail = node
        self._size += 1

    def get(self, index, get_prev=False):
        if index &lt; 0:
            index = self._size + index
        if index &lt; 0 or index &gt;= self.length:
            raise IndexError
        prev = None
        for i, node in enumerate(self):
            if i == index:
                if get_prev:
                    return node, prev
                else:
                    return node
            prev = node

    def remove(self, index):
        node, prev = self.get(index, get_prev=True)
        if node is self.head:
            self.head = node.next
        else:
            prev.next = node.next
        self._size -= 1
        return node

    def pop(self):
        return self.remove(self.length - 1)

    def __len__(self):
        return self._size
    length = property(__len__)
    size = property(__len__)

    def __iter__(self):
        curr = self.head
        while curr is not None:
            yield curr
            curr = curr.next
        raise StopIteration

    def __str__(self):
        return ', '.join([str(node.value) for node in self])

class Node(object):
    def __init__(self, val, next=None):
        self.value = val
        self.next = next
</pre>
<pre>import unittest
class Test_A_New_Linked_List(unittest.TestCase):

    def test_given_no_values_should_be_empty(self):
        list_ = LinkedList()
        assert list_.is_empty()

    def test_given_no_values_should_have_size_0(self):
        list_ = LinkedList()
        assert list_.size == list_.length == 0

    def test_given_values_should_not_be_empty(self):
        list_ = LinkedList(1, 2, 3)
        assert not list_.is_empty()
        assert [node.value for node in list_] == [1, 2, 3]

    def test_given_4_values_should_have_size_4(self):
        list_ = LinkedList(1, '2', 3, '4th value')
        assert list_.size == 4

class Test_An_Empty_List(unittest.TestCase):

    def test_should_have_size_1_after_add(self):
        list_ = LinkedList()
        val = 15
        list_.add(val)
        assert list_.head.value == list_.tail.value == val
        assert len(list_) == list_.length == list_.size == 1

    def test_should_raise_an_index_error_on_get(self):
        list_ = LinkedList()
        self.assertRaises(IndexError, list_.get, 1)
        list_ = LinkedList(1, 2, 3)
        list_.remove(0); list_.remove(0); list_.remove(0)
        self.assertRaises(IndexError, list_.get, 0)

    def test_should_raise_an_index_error_on_remove(self):
        list_ = LinkedList()
        self.assertRaises(IndexError, list_.remove, 1)
        list_ = LinkedList(1, 2, 3)
        list_.remove(0); list_.remove(0); list_.remove(0)
        self.assertRaises(IndexError, list_.remove, 0)

    def test_should_raise_an_index_error_on_pop(self):
        list_ = LinkedList()
        self.assertRaises(IndexError, list_.pop)

class Test_A_Non_Empty_List(unittest.TestCase):

    def test_should_increase_its_size_by_1_on_add(self):
        list_ = LinkedList(1, 2, 4, 5)
        starting_size = list_.size
        list_.add(13)
        assert len(list_) == list_.length == list_.size == (starting_size + 1)

    def test_should_return_a_node_on_get(self):
        list_ = LinkedList(1, 2, '3rd value')
        node = list_.get(0)
        assert isinstance(node, Node)
        assert node.value == 1
        node = list_.get(1)
        assert isinstance(node, Node)
        assert node.value == 2
        node = list_.get(2)
        assert isinstance(node, Node)
        assert node.value == '3rd value'

    def test_should_decrease_its_size_by_1_on_remove(self):
        list_ = LinkedList(1, 2, 4, 5)
        starting_size = list_.size
        list_.remove(0)
        assert len(list_) == list_.length == list_.size == (starting_size - 1)

    def test_should_decrease_its_size_by_1_on_pop(self):
        list_ = LinkedList(1, 2, 4, 5)
        starting_size = list_.size
        list_.pop()
        assert len(list_) == list_.length == list_.size == (starting_size - 1)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wyattbaldwin.com/2007/04/25/fun-with-python-bdd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

