TestCase

TestCase is the basic test case class for the HILSTER Testing Framework that should be used as a super class for a specialized test framework.

digraph inheritanceb4618a295e { rankdir=LR; size="8.0, 12.0"; "htf.core.TestCase" [fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5)",tooltip="``TestCase`` is the basic test case class for the HILSTER Testing Framework"]; "unittest.case.TestCase" -> "htf.core.TestCase" [arrowsize=0.5,style="setlinewidth(0.5)"]; "htf.testcase.TestCase" [fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5)",tooltip="``TestCase`` is the basic test case class for the HILSTER Testing Framework"]; "htf.core.TestCase" -> "htf.testcase.TestCase" [arrowsize=0.5,style="setlinewidth(0.5)"]; "unittest.case.TestCase" [fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5)",tooltip="A class whose instances are single test cases."]; }
class htf.TestCase(methodName=u'runTest')

TestCase is the basic test case class for the HILSTER Testing Framework that should be used using inheritance.

Parameters:methodName='runTest' (str) – the name of the test method to be run by the test runner.
afterTest()

This method is called after a test ends and before htf.unittest.testcase.TestCase.tearDown() is called. This method is injected using the htf.decorators.after() decorator to be run in the test context.

If you override this method, make sure to call the original implementation:

class SpecializedTestCase(TestCase):

    def afterTest(self):
        # your code goes here
        super(TestCase, self).afterTest()
expect(expectedValue, observedValue, errorMessage=None)

Expect that expectedValue and observedValue are the same. If expectedValue and observedValue differ an AssertionError is raised.

Parameters:
  • expectedValue – the expected value.
  • observedValue – the observed value that is compared to expectedValue.
  • errorMessage=None (str) – an optional message.
expectStep(title, expectedValue, observedValue, errorMessage=None)

Creates a test step in test report and on stdout using title. Expect that expectedValue and observedValue are the same. If expectedValue and observedValue differ an AssertionError is raised.

Parameters:
  • title (str) – the step’s title.
  • expectedValue – the value that is expected.
  • observedValue – the current observed value that is compared to expectedValue.
  • errorMessage=None (str) – an optional message.
log(*args)

Log *args to stdout and into the result of the given step if run in a step context block. This method is not thread-safe!

Parameters:*args (iterable) – a tuple of python objects that must be convertible into a string. All parameters are concatenated with spaces and converted to string before.
runBackground(func, name=None, joinTimeout=1, args=None, kwargs=None)

With this method you can run another method in background.

If this method uses a while loop, it must poll self._runThreadsEnable to be able to be terminated. If the background thread does not terminate, the foreground thread never ends!

Parameters:
  • func (callable) – the method to be run in background.
  • name=None (str) – a name for the background task. Default: None. If name is None func.__name__ is used.
  • joinTimeout=1 (float) – the timeout to be used when calling join on the thread.
  • args=None (tuple) – a tuple of positional arguments that are passed to the background task when it is called.
  • kwargs=None (dict) – a dictionary of keyword arguments that are passed to the background task when it is called.
runPeriodic(func, period, maximumPeriod=None, name=None, raiseException=True, args=None, kwargs=None)

With this method you can run another method periodically in background with a given period.

Parameters:
  • func (callable) – the method to be called periodically in background.
  • period (float) – the period in second.
  • maximumPeriod=None (float) – if set to a float >= period func may take up to maximumPeriod time without raising an exception. A warning is printed out to stdout instead.
  • name=None (str) – a name for the background task.
  • raiseExceptions=True – if set to True exceptions are put into the exception queue to let a test fail if a background thread fails.
  • args=None (tuple) – a tuple of positional arguments that are passed to the background task when it is called.
  • kwargs=None (dict) – a dictionary of keyword arguments that are passed to the background task when it is called.
Returns:

a callable object is returned that stops execution when called.

Return type:

stop-trigger (callable)

setOutputCaptureEnable(enabled=True)

Enables or disables capturing of stdout and stderr for later use in test reports.

This must be called before htf.TestCase.run() is called for example in htf.TestCase.__init__().

Parameters:enabled=True (bool) – the new enabled state
setUp()

This method is called from test runner before a test is executed to create the test-fixtures.

If you override this method, make sure to call the original implementation:

def setUp(self):
    super(TestCase, self).setUp()
     # your code goes here
step(title, callableObj=None, *args, **kwargs)

Run a test step that is documented in the test report.

Parameters:
  • title (str) – the step’s title.
  • callableObj=None (callable) – a callable object that is called within the step or None.
  • *args (tuple) – a tuple of positional arguments for the step’s context.
  • **kwargs (dict) – a dictionary of keyword arguments for the step’s context.

Usage:

with self.step(title="Description of this test step .."):
    # methodCall()
    self.assertTrue(True "Message in case of an error")

Or an equivalent approach:

self.step(title="Description of this test step comes here ..",
    self.assertTrue, True, "Message in case of an error")
# method calls are not possible here!
stopThread(nameOrFunction)

This method stops a specific thread with the name or function described by nameOrFunction by calling join() with join timeout supplied by runPeriodic() or runBackground() on it. It does not set a stop condition so the thread must end and must not include an endless loop. If the thread is still alive after the first join messages are printed to inform the user.

Parameters:nameOrFunction (str, callable) – the name or the function (reference) of the thread to be stopped.
Returns:the number of stopped threads.
Return type:int
Raises:Exception – if the thread was not found
stopThreads()

This method stops all background threads by setting self._runThreadsEnable to False and calling thread.join() until it is not alive anymore.

tearDown()

This method is called from test runner after a test was executed regardless of it’s result.

This method shall destroy all used fixtures.

If you override this method, make sure to call the original implementation:

def tearDown(self):
    # your code goes here
    super(TestCase, self).tearDown()

Example for a specialized test case:

Example:

class SpecializedTestCase(TestCase):

    def setUp(self):
        TestCase.setUp(self)

        # your code comes here

    def tearDown(self):
        # your code comes here

        TestCase.tearDown(self)

To create test cases in your specialized test framework you should again subclass the specialized test case like this:

class ASpecializedTest(SpecializedTestCase):
    """
    The test can be documented in reStructuredText markup which
    will be shown in the test reports.
    """

    def test_whatEver(self):
        """
        This test can have a comment in reStructuredText markup, too which
        will be shown in the test reports as well.
        """
        self.assertTrue(True)

    def test_anotherTestStep(self):
        """no comment"""
        self.assertTrue(True)

Examples to document test steps:

Test steps are automatically documented in the test report using the step() context block:

class Test(TestCase):
    def test_simpleStep(self):
        for ii in range(10):
            with self.step(title="step %i" % ii):
                self.assertTrue(True)

    def test_anotherSimpleStep(self):
        result = False
        self.step("Check that the result is True", self.assertTrue, result, "The result is not True")

    def test_longStep(self):
        with self.step(title="multiple assertions in one step"):
            self.assertTrue(True)
            self.assertFalse(False)
            # something else..
            self.assertTrue(result)

Examples for thread usage:

A background thread:

class TestTestCase(TestCase):
    def test_threadEndsNormally(self):
        """
        A thread is run in background that terminates normally.
        """
        def thread():
            print("thread starts")
            time.sleep(1)
            print("thread ends")
        self.runBackground(func=thread, name="thread", joinTimeout=2)

A background thread that ends later:

class TestTestCase(TestCase):
    def test_threadEndsLater(self):
        """
        A thread is run in background that terminates later.
        """
        def thread():
            print("thread starts")
            time.sleep(1)
            print("thread ends")
        self.runBackground(func=thread, name="thread", joinTimeout=.1)

A background thread with a while loop:

class TestTestCase(TestCase):
    def test_threadWithWhileLoop(self):
        """
        A thread is run in background with a while loop
        polling the `self._runThreadsEnable` variable.
        """
        def thread(*args, **kwargs):
            print("thread:", args, kwargs)
            print("thread starts")
            while self._runThreadsEnable:
                print("thread active")
                time.sleep(1)
                print("thread inactive")
            print("thread ends")
        self.runBackground(func=thread, name="thread", joinTimeout=1, args=(1, 2, 3,), kwargs={'blah' : 'blub'})
        time.sleep(3.0)

Periodic background execution:

class TestTestCase(TestCase):
    def test_runPeriodic(self):
        """
        A method is run in background periodically.
        """
        self._counter = 0

        def function(*args, **kwargs):
            print("function()")
            self._counter += 1

        stop = self.runPeriodic(func=function, period=1.0, name="periodic function", raiseException=True, args=(), kwargs={})
        time.sleep(2.5)
        self.assertTrue(self._counter == 3)

        stop()
        time.sleep(2.5)
        self.assertTrue(self._counter == 3)

Periodic background execution with parameters:

class TestTestCase(TestCase):
    def test_periodicAndBackgroundParameters(self):
        """
        A method is run in background peridically with parameters.
        """
        self._args = None
        self._kwargs = None

        def function(*args, **kwargs):
            print("function()")
            self._args = args
            self._kwargs = kwargs

        args = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        kwargs= {"foo" : "bar"}

        self.runPeriodic(func=function, period=1.0, name="periodic function", raiseException=True, args=args, kwargs=kwargs)
        time.sleep(2.5)

        print(self._args)
        print(self._kwargs)
        self.assertTrue(self._args == args)
        self.assertTrue(self._kwargs == kwargs)

A background thread that raises an exception:

class TestTestCase(TestCase):
    @expectedFailure
    def test_exceptionInBackgroundTask(self):
        """
        An exeption is raised in a background tasks that leads to an exception
        in the foreground task.
        """
        def function():
            raise Exception("Das ist ein Test!")

        self.runBackground(func=function, name="function")
        time.sleep(1.0)
        # tearDown() must be called here because it always leads to an Exception if run from TestRunner context!
        self.tearDown()