From 3f3ea4414837d5f2f09cc314d45d829ec54cd4c8 Mon Sep 17 00:00:00 2001 From: Erik Bernoth Date: Fri, 10 May 2013 16:24:29 +0200 Subject: [PATCH 1/2] test: import cleanup & nosetests intro While investigating how to deliver a clear user/developer interface for MONK's unittest suite, I found that `nosetests` is a rather powerful tool for testing. As far as I understand it is a framework/tooling around Python's unittest library adding more features. Those features include: - automatic test discovery, no more need for test suites (but still possible) - simpler test methods without TestCase overhead and without removing any feature - decorators for Exception testing -> simpler code - plugins for coverage - plugins for various xml output That's why nosetests seems to be the standard tool for unit testing in the Python community. Making the decision to use nosetests and the need to change the unittests to comply with the new virtualenv-install-import policy makes a rewrite of the existing unit tests rather attractive. This commit starts that approach, deleting all the old school unit tests (which can be retrieved later on if necessary anyway). The first test will be about serial_conn, because that is the next development focus for MONK. It imports monk_tf and creates a SerialConn object in a very code-effective nosetest. Then setup.cfg and setup.py were adapted. Now it is possible to simply call the following commands and let setuptools and nosetests do the rest: $ pip install -r test-env.txt $ python setup.py nosetests If there are errors running the installations you might miss the required packages: #Ubuntu $ sudo apt-get install python-dev libssh2-1-dev # or Fedora $ yum install python-devel libssh2-devel # Sorry, no idea on Suse and the others Here's the example for you to follow: # checkout a fresh MONK $ mkdir fresh $ cd fresh $ git clone git@github.com:DFE/MONK $ cd MONK # checkout this branch $ git checkout f-unittest-virtualenv # create a virtual conf to not play around with your system configuration $ virtualenv . $ source bin/activate # now let the tools do their jobs (MONK)$ pip install -r test-env.txt (MONK)$ python setup.py nosetests check if creating a SerialConn object works.. ok OK With using `$ python setup.py develop` it's also possible to change your code and test suite while also being able to unit test it with `$ python setup.py nosetests` on the fly. Google for `setuptools develop` or ask me, if you want to know more about that. Last but not least this commit changes the place of the monk_tf folder again. The reason is, that all the tools' default behaviour is to expect the structure without the src/ folder. Before we decided that the src/ folder would be a better choice, because then potential additional packages might be structured in a more readable fashion with monk_tf. Because different tools are interacting now and each has the same default expectation it seems more logical to follow that expectation in the future. That's why this commit changes the structure instead of configuring all the tools to our structure. See Github Issue #34. Signed-off-by: Erik Bernoth Acked-by: Eik Binschek Acked-by: Johannes Kroop --- {src/monk_tf => monk_tf}/__init__.py | 0 {src/monk_tf => monk_tf}/bcc.py | 0 {src/monk_tf => monk_tf}/connection.py | 0 {src/monk_tf => monk_tf}/device.py | 0 {src/monk_tf => monk_tf}/devicetestcase.py | 0 {src/monk_tf => monk_tf}/serial_conn.py | 0 {src/monk_tf => monk_tf}/ssh_conn.py | 0 setup.cfg | 14 ++ setup.py | 28 +-- test-env.txt | 6 + test/test_all.py | 41 ---- test/test_bcc.py | 260 --------------------- test/test_connection.py | 216 ----------------- test/test_device.py | 26 --- test/test_devicetestcase.py | 72 ------ test/test_serial_conn.py | 164 ++++++------- test/test_ssh_conn.py | 25 -- 17 files changed, 119 insertions(+), 733 deletions(-) rename {src/monk_tf => monk_tf}/__init__.py (100%) rename {src/monk_tf => monk_tf}/bcc.py (100%) rename {src/monk_tf => monk_tf}/connection.py (100%) rename {src/monk_tf => monk_tf}/device.py (100%) rename {src/monk_tf => monk_tf}/devicetestcase.py (100%) rename {src/monk_tf => monk_tf}/serial_conn.py (100%) rename {src/monk_tf => monk_tf}/ssh_conn.py (100%) create mode 100644 setup.cfg create mode 100644 test-env.txt delete mode 100755 test/test_all.py delete mode 100755 test/test_bcc.py delete mode 100755 test/test_connection.py delete mode 100755 test/test_device.py delete mode 100755 test/test_devicetestcase.py mode change 100755 => 100644 test/test_serial_conn.py delete mode 100755 test/test_ssh_conn.py diff --git a/src/monk_tf/__init__.py b/monk_tf/__init__.py similarity index 100% rename from src/monk_tf/__init__.py rename to monk_tf/__init__.py diff --git a/src/monk_tf/bcc.py b/monk_tf/bcc.py similarity index 100% rename from src/monk_tf/bcc.py rename to monk_tf/bcc.py diff --git a/src/monk_tf/connection.py b/monk_tf/connection.py similarity index 100% rename from src/monk_tf/connection.py rename to monk_tf/connection.py diff --git a/src/monk_tf/device.py b/monk_tf/device.py similarity index 100% rename from src/monk_tf/device.py rename to monk_tf/device.py diff --git a/src/monk_tf/devicetestcase.py b/monk_tf/devicetestcase.py similarity index 100% rename from src/monk_tf/devicetestcase.py rename to monk_tf/devicetestcase.py diff --git a/src/monk_tf/serial_conn.py b/monk_tf/serial_conn.py similarity index 100% rename from src/monk_tf/serial_conn.py rename to monk_tf/serial_conn.py diff --git a/src/monk_tf/ssh_conn.py b/monk_tf/ssh_conn.py similarity index 100% rename from src/monk_tf/ssh_conn.py rename to monk_tf/ssh_conn.py diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..51fbc71 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,14 @@ +[nosetests] +#should not be set to 1 until bug is fixed in nosetests project +verbosity=2 +detailed-errors=1 +#xml output for jenkins and the likes +with-xunit=1 +#coverage with xml as well +with-xcoverage=1 +#only cover the monk package and leave the rest of python alone +cover-package=monk_tf +debug=nose.loader +# options to be set later: +#pdb=1 +#pdb-failures=1 diff --git a/setup.py b/setup.py index 3a8e00f..3faf855 100755 --- a/setup.py +++ b/setup.py @@ -11,25 +11,27 @@ # 2 of the License, or (at your option) any later version. # -from distutils.core import setup +from setuptools import setup -project = 'monk_tf' -src_path = 'src' -version = '0.1.1' +project = "monk_tf" +version = "0.1.1" setup( name=project, version=version, - description = 'a test framework for embedded systems', - author = 'DResearch Fahrzeugelektronik GmbH', - author_email = 'project-monk@dresearch-fe.de', - url='https://github.com/DFE/MONK', + description = "a test framework for embedded systems", + author = "DResearch Fahrzeugelektronik GmbH", + author_email = "project-monk@dresearch-fe.de", + url="https://github.com/DFE/MONK", packages=[project], - package_dir = { '' : src_path }, + setup_requires = [ + "nose >= 1.0" + ], install_requires = [ - 'pyserial ==2.5', - 'pylibssh2 ==1.0.1' + "pyserial >=2.5", + "pylibssh2 >=1.0.1" ],provides = [ - '{} ({})'.format(project, version) - ] + "{} ({})".format(project, version) + ], + test_suite = "nose.collector" ) diff --git a/test-env.txt b/test-env.txt new file mode 100644 index 0000000..f04e673 --- /dev/null +++ b/test-env.txt @@ -0,0 +1,6 @@ +argparse==1.2.1 +coverage==3.6 +distribute==0.6.34 +nose==1.3.0 +nosexcover==1.0.8 +wsgiref==0.1.2 diff --git a/test/test_all.py b/test/test_all.py deleted file mode 100755 index 49523d5..0000000 --- a/test/test_all.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -import unittest - -from test_bcc import TestBcc -from test_connection import TestConnection -from test_device import TestDevice -from test_devicetestcase import TestDevicetestcase -from test_serial_conn import TestSerialConn -from test_ssh_conn import TestSshConn - - -class TestAll(unittest.TestSuite): - - def __init__(self): - self.addTest(TestBcc()) - self.addTest(TestConnection()) - self.addTest(TestDevice()) - self.addTest(TestDeviceTestcase()) - self.addTest(TestSerialConn()) - self.addTest(TestSshConn()) - - - -if __name__ == "__main__": - unittest.main() diff --git a/test/test_bcc.py b/test/test_bcc.py deleted file mode 100755 index 1bccf68..0000000 --- a/test/test_bcc.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - -import subprocess, atexit -import unittest - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -from bcc import Bcc - -# -# MOCKING -# - -# --- mocked functions --- -MOCK_atexit_func = None -def mock_atexit_register(func): - global MOCK_atexit_func - MOCK_atexit_func = func - - -def mock_check_output(cmd, stderr = None): - MOCK_subp_input.append([cmd, stderr]) - if MOCK_subp_raise: - raise MOCK_subp_raise - return MOCK_subp_retval - -# --- mock helper variables and functions --- - -MOCK_bcc_example_output_off = """status_cb: raw data: 01 00 02 00 00 00 17 0b 09 00 09 00 e7 00 09 0a 04 ac 00 f0 00 60 02 05 01 4e 00 9e 00 4f 00 00 00 00 00 00 05 -SPIs/SPOs: Ignition: off, HDD-Sense: closed, OXE_INT1: 0, OXE_INT2: 0, XOSC_ERR: 0, GPI-Power: off, HDD-Power: off -GPInputs 1..6: 0 0 0 0 0 0 GPOutputs 1..4: 0 0 0 0 RTC Temp : 23 deg C Accel X, Y, Z: 35mg, 35mg, 902mg -Voltages: 23.14V 11.96V 2.40V 0.96V 5.17V 3.34V 1.58V 0.79V 0.00V""" - -MOCK_bcc_example_output_on = """status_cb: raw data: 01 00 02 00 00 00 17 0b 09 00 09 00 e7 00 09 0a 04 ac 00 f0 00 60 02 05 01 4e 00 9e 00 4f 00 00 00 00 00 00 05 -SPIs/SPOs: Ignition: on, HDD-Sense: closed, OXE_INT1: 0, OXE_INT2: 0, XOSC_ERR: 0, GPI-Power: off, HDD-Power: on -GPInputs 1..6: 0 0 0 0 0 0 GPOutputs 1..4: 0 0 0 0 RTC Temp : 23 deg C Accel X, Y, Z: 35mg, 35mg, 902mg -Voltages: 23.14V 11.96V 2.40V 0.96V 5.17V 3.34V 1.58V 0.79V 0.00V""" - -MOCK_bcc_example_output_debugget = """debug_get_cb: addr: 0x00000001 len: 4 data: 12 34 23 42""" - -MOCK_subp_retval = "" -MOCK_subp_input = [ ] -MOCK_subp_raise = None - -def mock_reset_values(): - global MOCK_subp_input, MOCK_subp_retval, MOCK_subp_raise - MOCK_subp_input = [ ] - MOCK_subp_retval = "" - MOCK_subp_raise = None - -orig_ate_register = atexit.register -orig_subp_check_output = subprocess.check_output - -def mock_on(): - mock_reset_values() - atexit.register = mock_atexit_register - subprocess.check_output = mock_check_output - -def mock_off(): - atexit.register = orig_ate_register - subprocess.check_output = orig_subp_check_output - -# --- mocking ENDs --- - -# -# The actual tests -# - -class TestBcc(unittest.TestCase): - """ This class implements a number of default test cases - for the board controller class.""" - - def setUp(self): - mock_on() - - def tearDown(self): - mock_off() - - - def test_default_init_cleanup(self): - """ Test the default initialization and cleanup. - This test just checks for the correct defaults after - Bcc class instantiation. - Note that this test also implicitly tests bcc.poweron(), - which in turn tests bcc.hddpower and bcc.heartbeat setters.""" - - b = Bcc() - - # check instance variables - self.assertEquals(b._Bcc__drbcc, "drbcc") - self.assertEquals(b._Bcc__port, "/dev/ttyUSB0") - self.assertEquals(b._Bcc__port_br, 57600) - - # check function registered with atexit - self.assertEquals(b._Bcc__cleanup, MOCK_atexit_func) - - # check board controller commands issued during init - global MOCK_subp_input - self.assertEquals(len(MOCK_subp_input), 3) - self.assertEquals(MOCK_subp_input[0], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=debugset 16,0100010001'], subprocess.STDOUT]) - self.assertEquals(MOCK_subp_input[1], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=heartbeat 65535'], subprocess.STDOUT]) - self.assertEquals(MOCK_subp_input[2], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=hdpower 1'], subprocess.STDOUT]) - - # check atexit command - MOCK_subp_input = [] - MOCK_atexit_func() - self.assertEquals(len(MOCK_subp_input), 1) - self.assertEquals(MOCK_subp_input[0], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=debugset 16,00'], subprocess.STDOUT]) - - - def test_cleanup_fails(self): - """ This test checks for pokemon exception handling - in the cleanup atexit handler. """ - b = Bcc() - global MOCK_subp_raise - MOCK_subp_raise = Exception() - try: - MOCK_atexit_func() - except: - self.fail("BCC atexit function raised an exception!") - - - def __simple_setup(self, output, exc=None): - """ Helper for setting up simple tests. Will create a bcc instance and - do some initial cleanup. """ - b = Bcc() - global MOCK_subp_input, MOCK_subp_retval, MOCK_subp_raise - MOCK_subp_input = [] - MOCK_subp_retval = output - if exc: - MOCK_subp_raise = exc - return b - - - def test_cmd(self): - """ Test the execution of an arbitrary command """ - - b = self.__simple_setup("InDiesemStringDaSitztEinGeistUswUsf") - - rc, text = b.cmd("hurz") - - self.assertEquals(len(MOCK_subp_input), 1) - self.assertEquals(MOCK_subp_input[0][0][2],'--cmd=hurz') - - self.assertEquals(text, MOCK_subp_retval) - self.assertEquals(rc, 0) - - - def test_cmd_fails(self): - """ Test the execution of an arbitrary command which fails """ - - b = self.__simple_setup("bla", subprocess.CalledProcessError(9, "", "exception output")) - - rc, text = b.cmd("narf") - - self.assertEquals(len(MOCK_subp_input), 1) - self.assertEquals(MOCK_subp_input[0][0][2],'--cmd=narf') - - self.assertEquals(text, "exception output") - self.assertEquals(rc, 9) - - - def test_reset(self): - """ Test the reset function. """ - - import time - b = Bcc() - - called = [ 0, 0, 0 ] - s = time.sleep - def cb(a, idx): - a[idx] += 1 - - try: - b.poweroff = lambda: cb(called, 0) - time.sleep = lambda ignored: cb(called, 1) - b.poweron = lambda: cb(called, 2) - - b.reset() - - self.assertEquals(called, [1,1,1]) - finally: - time.sleep = s - - - def test_poweroff(self): - """ Poweroff test. Note that bcc.poweron() is already tested - by test_default_init_cleanup(). """ - b = self.__simple_setup(""); - - b.poweroff() - - self.assertEquals(len(MOCK_subp_input), 3) - self.assertEquals(MOCK_subp_input[0], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=debugset 16,0100000001'], subprocess.STDOUT]) - self.assertEquals(MOCK_subp_input[1], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=heartbeat 0'], subprocess.STDOUT]) - self.assertEquals(MOCK_subp_input[2], - [['drbcc', '--dev=/dev/ttyUSB0,57600', '--cmd=hdpower 0'], subprocess.STDOUT]) - - - def test_status(self): - """ Test the bcc status property. """ - - b = self.__simple_setup(MOCK_bcc_example_output_off) - text = b.status - - self.assertEquals(len(MOCK_subp_input), 1) - self.assertEquals(MOCK_subp_input[0][0][2],'--cmd=gets') - - self.assertEquals(text, MOCK_bcc_example_output_off) - - - def test_ignition(self): - """ Test the ignition prperty. """ - b = self.__simple_setup(MOCK_bcc_example_output_off) - self.assertFalse(b.ignition) - - b = self.__simple_setup(MOCK_bcc_example_output_on) - self.assertTrue(b.ignition) - - - def test_hddpower(self): - """ Test the hdd power prperty. """ - b = self.__simple_setup(MOCK_bcc_example_output_off) - self.assertFalse(b.hddpower) - - b = self.__simple_setup(MOCK_bcc_example_output_on) - self.assertTrue(b.hddpower) - - - def test_heartbeat(self): - """ test the heartbeat property. """ - b = self.__simple_setup(MOCK_bcc_example_output_debugget) - - curr, maxi = b.heartbeat - - self.assertEquals(curr, 4660) - self.assertEquals(maxi, 9026) - - -if __name__ == "__main__": - unittest.main() diff --git a/test/test_connection.py b/test/test_connection.py deleted file mode 100755 index ef01369..0000000 --- a/test/test_connection.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - - -import subprocess, atexit -import unittest - -from copy import deepcopy - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -from connection import Connection -import serial_conn -import ssh_conn - -# -# MOCKING -# - -# --- mocked functions --- - -class MockSerialConn(object): - instance = None - __called = { "__init__" : [], - "open" : [], - "cmd" : [] } - called = {} - - def __init__(self, login, skip_pass, boot_prompt, reset_cb): - MockSerialConn.called["__init__"].append( - (login, skip_pass, boot_prompt, reset_cb) ) - MockSerialConn.instance = self - - def open(self): - MockSerialConn.called["open"].append(True) - - def cmd(self, cmd): - MockSerialConn.called["cmd"].append(cmd) - if MOCK_sercmd_raise: - raise MOCK_sercmd_raise - return 0, MOCK_sercmd_ret - - -class MockSshConn(object): - - instance = None - - __called = { "__init__" : [], - "cmd" : [] } - called = {} - - def __init__(self, host, login): - MockSshConn.called["__init__"].append((host, login)) - MockSshConn.instance = self - - def cmd(self, cmd): - MockSshConn.called["cmd"].append(cmd) - if MOCK_sshcmd_raise: - raise MOCK_sshcmd_raise - return 0, MOCK_sshcmd_ret - -# --- mock helper variables and functions --- - -MOCK_sercmd_ret = "" -MOCK_sercmd_raise = None -MOCK_sshcmd_ret = "" -MOCK_sshcmd_raise = None - -def mock_reset_values(): - global MOCK_sercmd_raise, MOCK_sercmd_ret, MOCK_sshcmd_raise, MOCK_sshcmd_ret - MOCK_sercmd_raise = None - MOCK_sercmd_ret = "" - MOCK_sshcmd_raise = None - MOCK_sshcmd_ret = "" - MockSshConn.called = deepcopy(MockSshConn._MockSshConn__called) - MockSshConn.instance = None - MockSerialConn.called = deepcopy(MockSerialConn._MockSerialConn__called) - MockSerialConn.instance = None - -orig_serial_conn = serial_conn.SerialConn -orig_ssh_conn = ssh_conn.SshConn - -def mock_on(): - mock_reset_values() - serial_conn.SerialConn = MockSerialConn - ssh_conn.SshConn = MockSshConn - -def mock_off(): - serial_conn.SerialConn = orig_serial_conn - ssh_conn.SshConn = orig_ssh_conn - -# --- mocking ENDs --- - -# -# The actual tests -# - -class TestConnection(unittest.TestCase): - """ This class implements a number of default test cases - for the connection class.""" - - def setUp(self): - mock_on() - - def tearDown(self): - mock_off() - - - def test_default_init(self): - """ Test the default initialization. - This will implicitly test _serial_setup() as well. """ - c = Connection(network_setup = ("hurz", "bla-if0")) - - # check instance vars - self.assertEquals(c._login, ("root", "")) - self.assertEquals(c._target_if, "bla-if0") - self.assertEquals(c._serial, MockSerialConn.instance) - self.assertEquals(c.host, "hurz") - - # check initialisation of serial_conn class - self.assertEquals(len(MockSerialConn.called["__init__"]), 1) - self.assertEquals(MockSerialConn.called["__init__"][0], - (c._login, True, "HidaV boot on", None)) - self.assertEquals(len(MockSerialConn.called["open"]), 1) - self.assertEquals(MockSerialConn.called["open"][0], True) - - - def __ssh_test(self, c): - s = c._ssh - self.assertEquals(len(MockSshConn.called["__init__"]), 1) - self.assertEquals(MockSshConn.called["__init__"][0], (c.host, c._login)) - - def test_ssh(self): - """ Test for the ssh property. """ - c = Connection(network_setup = ("horst", "if-fi0")) - self.__ssh_test(c) - - # check for no initialization the second time 'round - MockSshConn.called["__init__"] = [] - s = c._ssh - self.assertEquals(len(MockSshConn.called["__init__"]), 0) - - # check for re-init after the property has been deleted - del c._ssh - self.__ssh_test(c) - - - def test_host(self): - """ Unittest for the host property. """ - c = Connection() - - # first, let the connection figure out the hot IP by itself - global MOCK_sercmd_ret - MOCK_sercmd_ret = "534.117.9.15" - self.assertEquals(c.host, MOCK_sercmd_ret) - - # then, check whether we can set it - c.host = "www.heise.de" - self.assertEquals(c.host, "www.heise.de") - - # finally: check the deleter and the getter's exception handling - del c.host - MOCK_sercmd_ret = "unparseable IP address" - self.assertRaises(Exception, lambda: c.host) - del c.host - - - def test_cmd(self): - """ Test for the command dispatcher. """ - global MOCK_sercmd_ret, MOCK_sshcmd_ret, MOCK_sshcmd_raise - MOCK_sercmd_ret = "Serial command execution" - MOCK_sshcmd_ret = "SSH command execution" - - c = Connection(network_setup = ("hurz", "bla-if0")) - MockSerialConn.called = deepcopy(MockSerialConn._MockSerialConn__called) - - # check for ssh command execution - self.assertEquals(c.cmd("test-command"), (0, MOCK_sshcmd_ret)) - - self.assertEquals(len(MockSshConn.called["cmd"]), 1) - self.assertEquals(MockSshConn.called["cmd"][0], "test-command") - self.assertEquals(len(MockSerialConn.called["cmd"]), 0) - - # generate an exception for ssh to check for serial execution - MOCK_sshcmd_raise = Exception() - self.assertEquals(c.cmd("test-2-command"), (0, MOCK_sercmd_ret)) - self.assertEquals(MockSerialConn.called["cmd"][0], "test-2-command") - self.assertEquals(len(MockSerialConn.called["cmd"]), 1) - - - def test_has_networking(self): - """ Test for the networking availability checker. """ - global MOCK_sercmd_ret - - c = Connection() - self.assertFalse(c.has_networking()) - - MOCK_sercmd_ret = "123.456.789.012" - self.assertTrue(c.has_networking()) - - -if __name__ == "__main__": - unittest.main() - diff --git a/test/test_device.py b/test/test_device.py deleted file mode 100755 index 9e0127a..0000000 --- a/test/test_device.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -import unittest - -class TestDevice(unittest.TestCase): - pass - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_devicetestcase.py b/test/test_devicetestcase.py deleted file mode 100755 index 8c91efe..0000000 --- a/test/test_devicetestcase.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - - -import unittest - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -import device -from devicetestcase import DeviceTestCase - -# -# MOCKING -# - -# --- mocked functions --- - -class MockDevice(object): - def __init__(self, devtype): - pass - def reboot(self, to_nand): - pass - -# --- mock helper variables and functions --- - -orig_device = device.Device - - -def mock_reset_values(): - pass - -def mock_on(): - device.Device = MockDevice - -def mock_off(): - device.Device = orig_device - -# --- mocking ENDs --- - -# -# The actual tests -# - -class TestDevicetestcase(unittest.TestCase): - """ This class implements a number of default test cases - for the devicetestcase class.""" - def setUp(self): - mock_on() - - def tearDown(self): - mock_off() - - - def test_get_device(self): - dev = DeviceTestCase.get_device( "test-dev" ) - - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_serial_conn.py b/test/test_serial_conn.py old mode 100755 new mode 100644 index ed62252..532155f --- a/test/test_serial_conn.py +++ b/test/test_serial_conn.py @@ -1,94 +1,102 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # # MONK Automated Testing Framework # -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH +# Copyright (C) 2012-2013 DResearch Fahrzeugelektronik GmbH, project-monk@dresearch-fe.de # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. +# 3 of the License, or (at you option) any later version. # - import logging -import unittest - -import monk_tf - -class TestSerialConn(unittest.TestCase): +from nose import tools as nt - def test_setting_read_timeout(self): - """shall test if read timeouts are set properly +from monk_tf import serial_conn as msc - The test mocks the pyserial API for setting this timeout. The API - contains a class Serial with the parameter `timeout` - (http://pyserial.sourceforge.net/pyserial_api.html#serial.Serial.timeout). - This is originally defined in `pyserial/serial/util.py` in class - `SerialBase` with the property-function `setTimeout`. - This test comes wit the MockSerial class underneath the TestCase, which - also contains this setter. But instead of setting real timeouts it - simply stores all values in a list this test. Afterwards those values - can be evaluated to find if the API seriously was used as expected. - """ - #prepare - start_rto = 591 - set_rto = -234 - #this contains always 2 calls, because read_until always writes both - # read- and writeTimeout - expected_rto = [ - set_rto, #written into old_rto - set_rto, #written into old_wto - start_rto, #written from old_rto - None #written from old_wto, which wasn't set - ] - target = "doesn't matter,rto" #just needed to fulfill API - sut = MockSerial(rto=start_rto, target=target) - #execute - monk_tf.serial_conn.SerialConn.read_until(sut, target, timeout=set_rto) - #assert - self.assertEqual(expected_rto, sut.results, - "expected: '{}', found: '{}'".format(expected_rto, sut.results)) - - - def test_setting_write_timeout(self): - """shall test if write timeouts are set properly - - The test mocks the pyserial API for setting this timeout. The API - contains a class Serial with the parameter `writeTimeout` - (http://pyserial.sourceforge.net/pyserial_api.html#serial.Serial.writeTimeout). - This is originally defined in `pyserial/serial/util.py` in class - `SerialBase` with the property-function `setTimeout`. - - This test comes wit the MockSerial class underneath the TestCase, which - also contains this setter. But instead of setting real timeouts it - simply stores all values in a list this test. Afterwards those values - can be evaluated to find if the API seriously was used as expected. - """ - #prepare - start_wto = 195 - set_wto = -342 - #this contains always 2 calls, because read_until always writes both - # read- and writeTimeout - expected_wto = [ - set_wto, #written into old_rto - set_wto, #written into old_wto - None, #written from old_rto, which wasn't set - start_wto #written from old_wto - ] - target = "doesn't matter,wto" #just needed to fulfill API - sut = MockSerial(wto=start_wto, target=target) - #execute - monk_tf.serial_conn.SerialConn.read_until(sut, target, timeout=set_wto) - #assert - self.assertEqual(expected_wto, sut.results, - "expected: '{}', found: '{}'".format(expected_wto, sut.results)) - - -class MockSerial(monk_tf.serial_conn.SerialConn): +def test_simple(): + """checks if creating a SerialConn object works + """ + #nothing to prepare + # + #execute + sut = msc.SerialConn() + #assert + nt.ok_(sut, "should contain a monk_tf.serial_conn.SerialConn object, but instead contains this: '{}'".format(sut)) + + +def test_setting_read_timeout(): + """shall test if read timeouts are set properly + + The test mocks the pyserial API for setting this timeout. The API + contains a class Serial with the parameter `timeout` + (http://pyserial.sourceforge.net/pyserial_api.html#serial.Serial.timeout). + This is originally defined in `pyserial/serial/util.py` in class + `SerialBase` with the property-function `setTimeout`. + + This test comes wit the MockSerial class underneath the TestCase, which + also contains this setter. But instead of setting real timeouts it + simply stores all values in a list this test. Afterwards those values + can be evaluated to find if the API seriously was used as expected. + """ + #prepare + start_rto = 591 + set_rto = -234 + #this contains always 2 calls, because read_until always writes both + # read- and writeTimeout + expected_rto = [ + set_rto, #written into old_rto + set_rto, #written into old_wto + start_rto, #written from old_rto + None #written from old_wto, which wasn't set + ] + target = "doesn't matter,rto" #just needed to fulfill API + sut = MockSerial(rto=start_rto, target=target) + #execute + msc.SerialConn.read_until(sut, target, timeout=set_rto) + #assert + nt.eq_(expected_rto, sut.results, + "expected: '{}', found: '{}'".format(expected_rto, sut.results)) + + +def test_setting_write_timeout(): + """shall test if write timeouts are set properly + + The test mocks the pyserial API for setting this timeout. The API + contains a class Serial with the parameter `writeTimeout` + (http://pyserial.sourceforge.net/pyserial_api.html#serial.Serial.writeTimeout). + This is originally defined in `pyserial/serial/util.py` in class + `SerialBase` with the property-function `setTimeout`. + + This test comes wit the MockSerial class underneath the TestCase, which + also contains this setter. But instead of setting real timeouts it + simply stores all values in a list this test. Afterwards those values + can be evaluated to find if the API seriously was used as expected. + """ + #prepare + start_wto = 195 + set_wto = -342 + #this contains always 2 calls, because read_until always writes both + # read- and writeTimeout + expected_wto = [ + set_wto, #written into old_rto + set_wto, #written into old_wto + None, #written from old_rto, which wasn't set + start_wto #written from old_wto + ] + target = "doesn't matter,wto" #just needed to fulfill API + sut = MockSerial(wto=start_wto, target=target) + #execute + msc.SerialConn.read_until(sut, target, timeout=set_wto) + #assert + nt.eq_(expected_wto, sut.results, + "expected: '{}', found: '{}'".format(expected_wto, sut.results)) + + +class MockSerial(msc.SerialConn): """mocks the :py:class:`serial.Serial` API It provides API like :py:class:`serial.Serial` and stores setter call @@ -131,7 +139,3 @@ def read(self): function, which is the only reason for it's existance. """ return self.target - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_ssh_conn.py b/test/test_ssh_conn.py deleted file mode 100755 index e200777..0000000 --- a/test/test_ssh_conn.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# MONK Automated Testing Framework -# -# Copyright (C) 2012 DResearch Fahrzeugelektronik GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version -# 2 of the License, or (at your option) any later version. -# - - -import sys, os, inspect -sys.path.append(os.path.abspath( - os.path.dirname(inspect.getfile(inspect.currentframe()))+"/../src/monk_tf")) - -import unittest - -class TestSshConn(unittest.TestCase): - pass - -if __name__ == '__main__': - unittest.main() From b91638103d51db7108ae4cacc18d531f1690b81a Mon Sep 17 00:00:00 2001 From: Erik Bernoth Date: Mon, 13 May 2013 16:42:48 +0200 Subject: [PATCH 2/2] .travis.yml: Update for simpler unittesting Because the interface for testing and installing did once more got closer to the standard, there is already a payoff in the travis-ci configuration, were now less lines of code are needed. In the new configuration the setuptools standard interface is used for installation as well as testing. The only requirements necessary for installation left are python2.7-dev and libssh2-1-dev, which are C-header dependencies needed for pylibssh2 to build. As far as I see there is not much we can do about those requirements for now. See Issue #34. Signed-off-by: Erik Bernoth Acked-by: Eik Binschek Acked-by: Johannes Kroop --- .travis.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ff49fa..18e6b71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,11 @@ python: - "2.7" install: - - "python setup.py sdist" - - "pip install dist/monk_tf-0.1.1.tar.gz" + - "pip install -r test-env.txt" + - "python setup.py develop" script: - - "python test/test_all.py" + - "python setup.py nosetests" before_install: - - "sudo apt-get install python2.7 python2.7-dev libssh2-1 libssh2-1-dev" - - "sudo apt-get install python-pip" + - "sudo apt-get install python2.7-dev libssh2-1-dev"