
BDD Case Study for Specter Framework

Specter uses the Boo meta-programming language (CLR .NET) to write well-read specifications.
Spectrum BDD Case Study
For our example, consider the specification of the Bender minibar, it will look like this:
import Specter.Framework
import Bender
context "At Bender's bar":
_bar as duck #our subject is defined in the setup block below
setup:
subject _bar = Bender.MiniBar()
#one-liner shorthand
specify { _bar.DrinkOneBeer() }.Must.Not.Throw()
specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5):
_bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5)
specify "If I drink more than ten beers then I get drunk":
for i in range(10):
_bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
* This source code was highlighted with Source Code Highlighter.
I would like to separately note the possibility of readability of this code by third-party people from programming.
What did we write?
Everything is very simple, we created the familiar NUnit TextFixture Class and described Test methods. Now I’ll tell you how it happened. Pay attention to the following line:
context "At Bender's bar":
* This source code was highlighted with Source Code Highlighter.
We define a certain context. What is he like? In fact, if we use the reflector in the assembly we get when compiling the specification, we find that this context is the TextFixture Class itself:
[NUnit.Framework.TestFixture]
class EmptyStack:
* This source code was highlighted with Source Code Highlighter.
Next, look at:
setup:
subject _bar = Bender.MiniBar()
* This source code was highlighted with Source Code Highlighter.
This is the usual SetUp for us:
[NUnit.Framework.SetUp]
public void SetUp()
{
subject _bar = Bender.MiniBar();
}
* This source code was highlighted with Source Code Highlighter.
The following line is interesting to us:
specify { _bar.DrinkOneBeer() }.Must.Not.Throw()
* This source code was highlighted with Source Code Highlighter.
It is already a test:
[NUnit.Framework.Test]
public void BarDrinkOneBeerMustNotThrow()
{
Assert.DoesNotThrow(_bar.DrinkOneBeer());
}
* This source code was highlighted with Source Code Highlighter.
Similarly, the following lines correspond:
specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5):
_bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5)
* This source code was highlighted with Source Code Highlighter.
The same tests:
[NUnit.Framework.Test]
public void IfIDrink5BeersThenIOwe5Bucks()
{
for (int i = 0; i == 5; i++)
_bar.DrinkOneBeer();
Int32MustModule.Must(_bar.Balance, “Bar balance must equal -5").Equal(-5);
}
* This source code was highlighted with Source Code Highlighter.
And one more line:
specify "If I drink more than ten beers then I get drunk":
for i in range(10):
_bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
* This source code was highlighted with Source Code Highlighter.
Conforms to:
[NUnit.Framework.Test]
public void IfiDrinkMoreThanTenBeersThenIGetDrunk()
{
for (int i = 0; i == 10; i++)
{
_bar.DrinkOneBeer();
}
Assert.Throws((typeof(InvalidOperationException), _bar.DrinkOneBeer()); }
* This source code was highlighted with Source Code Highlighter.
The specification is over, then we need to write the CODE of our application, because specter swore that the specification was not implemented:
![minibar-result1 [1] minibar-result1 [1]](https://habrastorage.org/getpro/habr/post_images/c94/e70/b12/c94e70b12801420e9585b6e79395436d.jpg)
Well, we are implementing our minibar:
namespace Bender
class MiniBar:
pass
* This source code was highlighted with Source Code Highlighter.
And add the necessary method:
namespace Bender
class MiniBar:
def DrinkOneBeer():
pass
[getter(Balance)]
_balance = 0
* This source code was highlighted with Source Code Highlighter.
Nevertheless, specter is not satisfied, since our method does not implement the work with balance described in the specification:
![minibar-result2 [1] minibar-result2 [1]](https://habrastorage.org/getpro/habr/post_images/4ec/70b/2b4/4ec70b2b4d9f33109524b8d45bd6f7fa.jpg)
We have to add an implementation:
namespace Bender
class MiniBar:
def DrinkOneBeer():
_balance-- if _balance <-10: raise System.Exception ("i'm drunk")[getter(Balance)]
_balance = 0
* This source code was highlighted with Source Code Highlighter.
In my opinion, the specter liked everything:
![minibar-result3 [1] minibar-result3 [1]](https://habrastorage.org/getpro/habr/post_images/6b1/641/c38/6b1641c38396f27dd2722e94b1f06a2a.jpg)
Great, so we practiced BDD.
So, we get unit tests that are familiar to us, however, the motivation for writing changes a bit, and we also acquire such an opportunity as providing the specter specification of tests as documentation. I think this is a great idea!
Resources
You can read about BDD here:
http://habrahabr.ru/blogs/testing/52929/ (about BDD in Russian using RSpec as an example, there are links at the end of the article)
Getting to know Behavior Driven Development (BDD) (Russian)
You can download Specter here:
http://specter.sourceforge.net/