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.
-
class
htf.
TestCase
(methodName='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 thehtf.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
andobservedValue
are the same. IfexpectedValue
andobservedValue
differ anAssertionError
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. IfexpectedValue
andobservedValue
differ anAssertionError
is raised.Parameters:
-
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 isNone
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 tomaximumPeriod
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 inhtf.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: 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 callingjoin()
with join timeout supplied byrunPeriodic()
orrunBackground()
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
toFalse
and callingthread.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()