Tests

To run the tests, execute the test.sh script in the root directory.

The majority of my tests are black box tests that ensure given a particular fragment of code, a particular output is achieved. To do this, I created a custom should_dsl matcher that will let me do this:

class Test_Tokenisor_translation(object):
    def setUp(self):
        self.toka = Tokeniser(with_describe_attrs=False)

    def test_it_should_translate_a_describe(self):
        (self.toka, 'describe "Something testable"') |should| result_in('class TestSomethingTestable (object ):pass')

The matcher takes (tokeniser, original) on the left and expects a string on the right. It will use the tokeniser provided to translate the original string, followed by comparing that result to the string on the right.

Note

NoseOfYeti doesn’t have any say on space between tokens and so the output can have some weird spacing.

Below is the specs that noseOfYeti has. To see the original source, just click a spec.

imports_test.py

Test DetermineImports

extra imports are added

it returns nothing if no imports

extra imports added before defaults

extra imports not added if no defaults

translation_tokeniser_test.py

Test Tokenisor translation

setUp

translates an it

has ignorable its

translates a describe

turns before each into setup

no transform inside expression

turns after each into teardown

it allows default arguments for its

turns an it without colon into skippable

gives setups super call when in describes

gives teardowns super call when in describes

adds arguments to its if declared on same line

indentation should work for inline python code

sets testname on non alphanumeric test names

can properly dedent after block of just containers

indentation should work regardless of crazy groups

indentation for test should work after skipped

it maintains line numbers when pass on another line

no added arguments to its if not declared on same line

indentation for describe should work after skipped

it doesn’t add semicolon after noy setup if not necessary

it keeps comments placed after setup and teardown methods

allows definition of different base class for next describe

gives teardowns super call that awaits when in describes and async

adds arguments to its if declared on same line and work with skipTest

gives setups super call when in describes that know about await if async

it has the ability to wrap setup and tearDown instead of inserting sup call

it is possible to have indented block after setup with wrapped setup option

it has the ability to wrap async setup and tearDown instead of inserting sup call

nesting_tokeniser_test.py

Test Tokeniser Nesting

setUp

works with tabs

works with space

works with tabs and inline pass

works with space and inline pass

keeps good indentation in body with tabs

keeps good indentation in body with spaces

names nested describes with part of parents name

support_test.py

TestWrapWorks

it ensures setUp from super classes get called

it ensures tearDown from super classes get called

test_chooser_test.py

Test TestChooser

it resets done when told about new module

already visited puts kls name key in done or returns True

.consider() method

it ignores functions already visited

it ignores if method starts with ignore

it ignores if method has kls in ignoreKls

it ignores if method has test set to false

it returns None if kls does not have is noy test set

it ignores inherited tests if is noy test is set on kls

it ignores parent if specified to only run tests in children

it runs parent tests in child if specified in parent to only run tests in children

it doesn’t run grandparent tests if specified in grandparent to only run tests in children

config_util_test.py

config util initialisation

config util normalising keys

Test ConfigUtil ApplyingConfigFile

it sets options from an json file

it doesn’t override existing non default values

Test ConfigUtil FindingConfigFile

setUp

it defaults to noyjson

        @wraps(fn)
        def caller(*args, **kw):
            fakes = self.__enter__()
            if not isinstance(fakes, (tuple, list)):
                fakes = [fakes]
            args += tuple(fakes)
            value = None
            try:
                value = fn(*args, **kw)
            except:
                etype, val, tb = sys.exc_info()
                self.__exit__(etype, val, tb)
                raise etype, val, tb
            else:
                self.__exit__(None, None, None)
            return value

it doesn’t care if default doesn’t exist

        @wraps(fn)
        def caller(*args, **kw):
            fakes = self.__enter__()
            if not isinstance(fakes, (tuple, list)):
                fakes = [fakes]
            args += tuple(fakes)
            value = None
            try:
                value = fn(*args, **kw)
            except:
                etype, val, tb = sys.exc_info()
                self.__exit__(etype, val, tb)
                raise etype, val, tb
            else:
                self.__exit__(None, None, None)
            return value

it complains if config file doesn’t exist

        @wraps(fn)
        def caller(*args, **kw):
            fakes = self.__enter__()
            if not isinstance(fakes, (tuple, list)):
                fakes = [fakes]
            args += tuple(fakes)
            value = None
            try:
                value = fn(*args, **kw)
            except:
                etype, val, tb = sys.exc_info()
                self.__exit__(etype, val, tb)
                raise etype, val, tb
            else:
                self.__exit__(None, None, None)
            return value

it doesn’t care if provided default doesn’t exist

        @wraps(fn)
        def caller(*args, **kw):
            fakes = self.__enter__()
            if not isinstance(fakes, (tuple, list)):
                fakes = [fakes]
            args += tuple(fakes)
            value = None
            try:
                value = fn(*args, **kw)
            except:
                etype, val, tb = sys.exc_info()
                self.__exit__(etype, val, tb)
                raise etype, val, tb
            else:
                self.__exit__(None, None, None)
            return value

Test ConfigUtil FindingValue

it returns value as is

it returns actual value if finds default

it raises attributeError when key doesn’t exist

Test ConfigUtil UsingConfigFile

it doesn’t care if no config file

    @wraps(method)
    def clear_and_verify(*args, **kw):
        clear_expectations()
        clear_calls()
        try:
            v = method(*args, **kw)
            verify() # if no exceptions
        finally:
            clear_expectations()
        return v

it applies config file if one is found

    @wraps(method)
    def clear_and_verify(*args, **kw):
        clear_expectations()
        clear_calls()
        try:
            v = method(*args, **kw)
            verify() # if no exceptions
        finally:
            clear_expectations()
        return v

Test ConfigUtil UsingOptions

it normalises keys

it overrides all values

it puts options in values

it works with list of tuples

it uses extractor if provided

it doesn’t complain if extractor returns none

complex_tokeniser_test.py

Test Tokeniser Complex

setUp

works with tabs

works with space

keeps good indentation in body with tabs

keeps good indentation in body with spaces

spec_codec_test.py

Test RegisteringCodec

not registering codec leads to error

registering codec doesn’t lead to error

config_test.py

Test ConfigAttributes

config gets attributes from util

    @wraps(method)
    def clear_and_verify(*args, **kw):
        clear_expectations()
        clear_calls()
        try:
            v = method(*args, **kw)
            verify() # if no exceptions
        finally:
            clear_expectations()
        return v

config gets values like attributes

Test ConfigSetup

setup uses util

        @wraps(fn)
        def caller(*args, **kw):
            fakes = self.__enter__()
            if not isinstance(fakes, (tuple, list)):
                fakes = [fakes]
            args += tuple(fakes)
            value = None
            try:
                value = fn(*args, **kw)
            except:
                etype, val, tb = sys.exc_info()
                self.__exit__(etype, val, tb)
                raise etype, val, tb
            else:
                self.__exit__(None, None, None)
            return value

it uses extractor if provided

it updates values with options

it gets values from config file

it overwrites config file with options

Test Default

stringify returns value

general_tokeniser_test.py

Test Tokeniser

no newline in default imports

is possible to turn off attributes

no newline in extended default imports

gives describes noy specific attributes

tokeniser has no default imports by default

determine imports imports nothing by default

is possible to specify extra imports without default imports

Fork me on GitHub