Case¶
Case class is abstraction platform for your test script. It can to be as function for usability only. So, example usage is below.
Simple usage¶
- Case can to be as:
- class
- function
- static function
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
class TestCase(seismograph.Case):
def test_something(self):
# do something
@suite.register
class StepsTestCase(seismograph.Case):
@seismograph.step(1, 'step one')
def one(self):
# do something
@seismograph.step(2, 'step two')
def two(self):
# do something
@suite.register
def function_test(case):
# do something
@suite.register(static=True)
def static_function_test():
# do something
if __name__ == '__main__':
seismograph.main()
How to use assertion¶
You can to check result of test script with help assertion object. Look at example...
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
class ExampleCase(seismograph.Case):
def test(self):
self.assertion.true(1 == 1)
@suite.register
def function_test(case):
case.assertion.equal(1, 1)
@suite.register(static=True)
def static_function_test():
seismograph.assertion.false(1 == 2)
if __name__ == '__main__':
seismograph.main()
Assertion class. How to change it?¶
-
class
seismograph.case.
AssertionBase
¶ -
almost_equal
(first, second, places=None, msg=None, delta=None)¶ Like assertAlmostEqual in unittest
-
dict_equal
(d1, d2, msg=None)¶ Like assertDictEqual in unittest
-
equal
(first, second, msg=None)¶ Like assertEqual in unittest
-
equal_by_iter
(seq1, seq2, msg=None)¶ Compare two iterable objects.
Example:
assertion.equal_by_iter(['hello', 'world'], set(['hello', 'world'])). assertion.equal_by_iter(dict(a=1, b=2), ('a', 'b))
-
fail
(msg=None)¶ Raised AssertionError with message
-
false
(expr, msg=None)¶ Like assertFalse in unittest
-
greater
(a, b, msg=None)¶ Like assertGreater in unittest
-
is_in
(member, container, msg=None)¶ Like assertIn in unittest
-
is_instance
(obj, cls, msg=None)¶ Like assertIsInstance in unittest
-
is_none
(obj, msg=None)¶ Like assertIsNone in unittest
-
is_not_in
(member, container, msg=None)¶ Like assertNotIn in unittest
-
is_not_none
(obj, msg=None)¶ Like assertIsNotNone in unittest
-
len_equal
(a, b, msg=None)¶ Check equal from length of list or tuple
len_equal([1, 2, 3], 3)
-
not_almost_equal
(first, second, places=None, msg=None, delta=None)¶ Like assertNotAlmostEqual in unittest
-
not_equal
(first, second, msg=None)¶ Like assertNotEqual in unittest
-
raises
(exc_class, callable_obj=None, *args, **kwargs)¶ Like assertRaises in unittest
-
sequence_equal
(seq1, seq2, msg=None, seq_type=None)¶ Like assertSequenceEqual in unittest
-
true
(expr, msg=None)¶ Like assertTrue in unittest
-
If you use case as function then you want to change assertion class, maybe, you can do it so...
import seismograph
suite = seismograph.Suite(__name__)
class ExampleAssertion(seismograph.AssertionBase):
def is_string(string, msg=None):
self.is_instance(string, str, msg=msg)
@suite.register
class ExampleCase(seismograph.Case):
__assertion_class__ = ExampleAssertion
def test(self):
self.assertion.is_string('hello')
@suite.register(assertion_class=ExampleAssertion)
def function_test(case):
case.assertion.is_string('hello')
if __name__ == '__main__':
seismograph.main()
Case class. How to change it during registration?¶
Let you be writing test as simple function then you want to change case class maybe :) This is doing so...
import seismograph
suite = seismograph.Suite(__name__)
class ExampleCase(seismograph.Case):
def print_hello(self):
print('Hello world!')
@suite.register(case_class=ExampleCase)
def function_test(case):
case.print_hello()
class ExampleCase2(seismograph.Case):
def setup(self):
print('Hello world!')
def teardown(self):
print('Good bye world!')
@suite.register(static=True, case_class=ExampleCase2)
def static_function_case():
print('I am running!')
if __name__ == '__main__':
seismograph.main()
How to use setup and teardown callbacks¶
This is xunit ideology. We support it.
import seismograph
suite = seismograph.Suite(__name__)
class ExampleCase(seismograph.Case):
@classmethod
def setup_class(cls):
# do something
def setup(self):
# do something
def teardown(self):
# do something
@classmethod
def teardown_class(cls):
# do something
@suite.register
class MyTestCase(ExampleCase):
def test_something(self):
# do something
if __name__ == '__main__':
seismograph.main()
Ho to use case by steps¶
This can to be useful for case with complex logic. Let look at this...
import seismograph
suite = seismograph.Suite(__name__)
class StepByStepCase(seismograph.Case):
def setup(self):
# do something
def begin(self):
# do something
@seismograph.step(1, 'step one')
def one(self):
# do something
@seismograph.step(2, 'step two')
def two(self):
# do something
def finish(self):
# do something
def teardown(self):
# do something
if __name__ == '__main__':
seismograph.main()
Begin method will be called after setup and finish before teardown. Need to remember, finish method can’t to be called if any exception was raised before.
Step performer¶
if you want to get control for execution step method then you should to use performer function. It’s easy, look at this... :)
import logging
import seismograph
logger = logging.getLogger(__name__)
suite = seismograph.Suite(__name__)
def step_log(case, method):
result = method()
if result:
logger.info(result)
class StepByStepCase(seismograph.Case):
@seismograph.step(1, 'step one', performer=step_log)
def one(self):
return 'hello'
@seismograph.step(2, 'step two', performer=step_log)
def two(self):
return 'world'
if __name__ == '__main__':
seismograph.main()
How to use flows. What is it?¶
If you have only one test script and many context for it, so you can to use flows for execution.
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
class ExampleCaseClass(seismograph.Case):
__flows__ = (
seismograph.Context(
text='some text',
),
seismograph.Context(
text='some text',
),
)
def test(self, ctx):
print(ctx.text)
@suite.register
class ExampleCaseClass2(seismograph.Case):
@seismograph.flows(
seismograph.Context(
text='some text',
),
seismograph.Context(
text='some text',
),
)
def test(self, ctx):
print(ctx.text)
@suite.register
class StepsCase(seismograph.Case):
__flows__ = (
seismograph.Context(
text='some text',
),
seismograph.Context(
text='some text',
),
)
@seismograph.step(1, 'step one')
def one(self, ctx):
print(ctx.text)
@seismograph.step(2, 'step two')
def two(self, ctx):
print(ctx.text)
@seismograph.flows(
seismograph.Context(
text='some text',
),
seismograph.Context(
text='some text',
),
)
@suite.register
def function_test(case, ctx):
print(ctx.text)
@seismograph.flows(
seismograph.Context(
text='some text',
),
seismograph.Context(
text='some text',
),
)
@suite.register(static=True)
def static_function_test(ctx):
print(ctx.text)
if __name__ == '__main__':
seismograph.main()
How to use skip¶
Skip test or case is doing like in unittest framework. I think, it’s no problem for you :)
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
class CaseExample(seismograph.Case):
@seismograph.skip('TODO')
def test(self):
# do something
@seismograph.skip_unless(False, 'TODO')
@suite.register
class CaseExample(seismograph.Case):
def test_one(self):
# do something
def test_two(self):
# do something
@seismograph.skip_if(True, 'TODO')
@suite.register
def function_test(case):
# do something
if __name__ == '__main__':
seismograph.main()
Also, you can to use simple skip on registration case. Should to use keyword argument “skip” for that.
How to require extensions¶
You can to use extensions for your tests script. Extensions should to configure in config.
import seismograph
suite = seismograph.Suite(__name__)
@suite.register(require=['selenium'])
def test_google_search(case):
with case.ext('selenium') as browser:
browser.go_to('http://google.com')
browser.input(name='q').set('python')
browser.button(name='btnG').click()
selenium.assertion.text_in(browser, 'python')
if __name__ == '__main__':
seismograph.main()
How to use case log. What is it?¶
Log object does store output in buffer for a while test case is running. Log will be flushed to stream after run. This give a chance to get sorted output while program is async running.
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
def function_test(case):
case.log('Hello world!')
if __name__ == '__main__':
seismograph.main()
How can i add info to error reason?¶
This is reason of crash by any problem. It will save to xunit report and write to console.
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
def function_test(case):
case.reason_storage['username'] = 'John Smith'
case.assertion.true(False)
if __name__ == '__main__':
seismograph.main()
How can i to repeat test method?¶
It happens when is necessity to call test method within different settings. This is for example only...
import requests
import seismograph
suite = seismograph.Suite(__name__)
class Client(object):
def __init__(self, addr, protocol=None):
self._addr = addr
self._protocol = protocol or 'http'
@property
def url(self):
return '{}://{}'.format(self._protocol, self._addr)
def switch_protocol(self, protocol):
self._protocol = protocol
def get(self, path, **kw):
requests.get(self.url, **kw)
@suite.register
class ExampleCase(seismograph.Case):
protocols = (
'http',
'https',
)
client = Client('google.com')
def __repeat__(self):
for protocol in self.protocols:
self.client.switch_protocol(protocol)
yield
def test(self):
self.client.get('/')
if __name__ == '__main__':
seismograph.main()
How to prepare test method?¶
Sometimes we are needing to change test method and wrap it. You can do it so...
import seismograph
suite = seismograph.Suite(__name__)
@suite.register
class ExampleCase(seismograph.Case):
def __prepare__(self, method):
def wrapper():
print('Start')
method()
print('Stop')
return wrapper
def test(self):
print('Run')
if __name__ == '__main__':
seismograph.main()