As found in the example directory:
The way nose-of-yeti works is when a file with the necessary codec is imported, it will be translated into python code before being executed. This has the nice side effect that using a nose-of-yeti spec is transparently handled via python mechanisms, and once you have a .pyc file, it doesn’t need to do the translation again (untill you either delete the .pyc or change the file).
To tell python to use the correct encoding, you first let nose-of-yeti register it’s codec (it comes with a plugin for both nose and pylint for this) and then you have # coding: spec
as the first line of the file.
# coding: spec
# This is a comparison of dsl syntax to what is generated
########################
### BEFORE
########################
# coding: spec
from noseOfYeti.tokeniser.support import noy_sup_setUp
from unittest import TestCase
import nose
it 'can exist without a describe'
it 'can have args', blah=1
describe TestCase, 'numbers':
before_each:
self.number1 = 1
self.number2 = 2
it 'has number1 as 1':
self.assertEqual(self.number1, 1)
ignore 'some test that I want to be named so it isnt ran':
pass
it 'is skipped'
describe 'testing number 3':
before_each:
self.number3 = 3
it 'has number1 from the lower level describe':
self.assertEqual(self.number1, 1)
it 'also has number3':
self.assertEqual(self.number3, 3)
it "works when I have non alphanumeric characters in the test name, things like ' or %":
self.assertEqual(5, 5)
it "can have arguments", arg1=2, arg2=4:
self.assertEqual(arg2, 4)
it "maintains newlines to keep line numbers same in exceptions":
pass
describe "let's change a number":
before_each:
self.number1 = 4
it 'changed number1 but kept others the same':
self.assertEqual(self.number1, 4)
self.assertEqual(self.number2, 2)
self.assertEqual(self.number3, 3)
########################
### AFTER
### Note that I did clean it up very slightly
########################
from noseOfYeti.tokeniser.support import noy_sup_setUp
from unittest import TestCase
import nose
def test_can_exist_without_a_describe(): raise nose.SkipTest
def test_can_have_args(blah=1): raise nose.SkipTest
class TestNumbers(TestCase):
def setUp(self):
noy_sup_setUp(super(TestNumbers, self)); self.number1 = 1
self.number2 = 2
def test_has_number1_as_1(self):
self.assertEqual(self.number1, 1)
def ignore__some_test_that_I_want_to_be_named_so_it_isnt_ran(self):
pass
def test_is_skipped(self): raise nose.SkipTest
class TestNumbers_TestingNumber3(TestNumbers):
def setUp(self):
noy_sup_setUp(super(TestNumbers_TestingNumber3, self)); self.number3 = 3
def test_has_number1_from_the_lower_level_describe(self):
self.assertEqual(self.number1, 1)
def test_also_has_number3 (self ):
self.assertEqual(self.number3, 3)
def test_works_when_I_have_non_alphanumeric_characters_in_the_test_name_things_like_or(self):
self.assertEqual(5, 5)
def test_can_have_arguments(self, arg1 = 2, arg2 = 4):
self.assertEqual(arg2, 4)
def test_maintains_newlines_to_keep_line_numbers_same_in_exceptions(self):
pass
class TestNumbers_TestingNumber3_LetsChangeANumber(TestNumbers_TestingNumber3):
def setUp(self):
noy_sup_setUp(super(TestNumbers_TestingNumber3_LetsChangeANumber, self))
self.number1 = 4
def test_changed_number1_but_kept_others_the_same(self):
self.assertEqual(self.number1, 4)
self.assertEqual(self.number2, 2)
self.assertEqual(self.number3, 3)
TestNumbers.is_noy_spec= True
TestNumbers_TestingNumber3.is_noy_spec= True
TestNumbers_TestingNumber3_LetsChangeANumber.is_noy_spec = True
TestNumbers_TestingNumber3.test_works_when_I_have_non_alphanumeric_characters_in_the_test_name_things_like_or.__func__.__testname__ = "works when I have non alphanumeric characters in the test name, things like ' or %"
# coding: spec
# The noy plugin for nosetests (enabled by the --with-noy option)
# will register the "spec" codec, which means any file that has
# "# coding: sepc" as the first line, like this file, will be parsed
# by the spec codec before it is imported.
# The codec will then turn what you have written into proper
# , executable python code!
# The test can then be specified using describes and its
import nose
it "is possible to add numbers":
self.assertEqual(1 + 1, 2)
it "is possible to add the number three", three=3:
# Contrived example of default arguments
self.assertEqual(1 + three, 4)
describe "Python Mathematics":
# That is replaced with "class test_Python_Mathematics(object):"
it 'is be able to add two numbers':
# that is replaced with "def test_is_able_to_add_two_numbers(self):"
self.assertEqual(2 + 3, 5)
self.assertEqual(2 + 0, 2)
it "can't divide by zero":
with self.assertRaises(ZeroDivisionError):
2 / 0
it 'does this other thing'
# Because it doesn't have colon at the end it will be a skipped test.
# Which means it adds a raise nose.SkipTest for you
# "def test_does_this_other_thing(self): raise nose.SkipTest"
# Note that if you don't have the "with-default-imports" option set,
# then it is up to you to import nose
# We can also define a class for the describes
# Either when we create the tokeniser and register it
# Or inside the spec file itself, per describe
class DifferentBase(object):
def x(self):
return 5
describe DifferentBase 'Inheritance':
it 'has an x equal to 5':
self.assertEqual(self.x(), 5)
# You can even nest describes !
# The following is a bad example, but it demonstrates well enough
describe 'numbers':
before_each:
self.number1 = 1
self.number2 = 2
it 'has number1 as 1':
self.assertEqual(self.number1, 1)
describe 'testing number 3':
before_each:
self.number3 = 3
it 'has number1 from the lower level describe':
self.assertEqual(self.number1, 1)
it 'also has number3':
self.assertEqual(self.number3, 3)
describe "let's change a number":
before_each:
self.number1 = 4
it 'changed number1 but kept others':
self.assertEqual(self.number1, 4)
self.assertEqual(self.number2, 2)
self.assertEqual(self.number3, 3)