Package rostest :: Module baretest

Source Code for Module rostest.baretest

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2010, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: launch.py 8960 2010-04-07 23:54:50Z kwc $ 
 34   
 35  """ 
 36  rostest implementation of running bare (gtest-compatible) unit test 
 37  executables. These do not run in a ROS environment. 
 38  """ 
 39   
 40  import os 
 41  import unittest 
 42  import time 
 43   
 44  import roslib.packages 
 45   
 46  import roslaunch.pmon 
 47   
 48  from rostest.rostestutil import createXMLRunner, printSummary, printRostestSummary, \ 
 49      xmlResultsFile, rostest_name_from_path, printlog, printlogerr 
 50  import rostest.xmlresults 
 51   
 52  BARE_TIME_LIMIT = 60. 
 53   
54 -class BareTestCase(unittest.TestCase):
55
56 - def __init__(self, exe, args, results, retry=0, time_limit=None, test_name=None):
57 """ 58 @param exe: path to executable to run 59 @type exe: str 60 @param args: arguments to exe 61 @type args: [str] 62 @param results: test results accumulator 63 @param retry: (optional) number of retries for test 64 @type retry: int 65 @param time_limit: (optional) time limit for test. Defaults to BARE_TIME_LIMIT. 66 @type time_limit: float 67 @param test_name: (optional) override automatically geneated test name 68 @type test_name: str 69 """ 70 super(BareTestCase, self).__init__() 71 self.results = results 72 _, self.package = roslib.packages.get_dir_pkg(exe) 73 self.exe = exe 74 if test_name is None: 75 self.test_name = os.path.basename(exe) 76 else: 77 self.test_name = test_name 78 79 self.args = [self.exe] + args 80 self.retry = retry 81 self.time_limit = time_limit or BARE_TIME_LIMIT 82 self.pmon = None
83
84 - def setUp(self):
85 self.pmon = roslaunch.pmon.start_process_monitor()
86
87 - def tearDown(self):
88 if self.pmon is not None: 89 roslaunch.pmon.shutdown_process_monitor(self.pmon) 90 self.pmon = None
91
92 - def runTest(self):
93 self.failIf(self.package is None, "unable to determine package of executable") 94 95 done = False 96 while not done: 97 test_name = self.test_name 98 99 printlog("Running test [%s]", test_name) 100 101 #setup the test 102 # - we pass in the output test_file name so we can scrape it 103 test_file = xmlResultsFile(self.package, test_name, False) 104 if os.path.exists(test_file): 105 printlog("removing previous test results file [%s]", test_file) 106 os.remove(test_file) 107 108 self.args.append('--gtest_output=xml:%s'%test_file) 109 110 # run the test, blocks until completion 111 printlog("running test %s"%test_name) 112 timeout_failure = False 113 114 run_id = None 115 #TODO: really need different, non-node version of LocalProcess instead of these extra args 116 process = roslaunch.nodeprocess.LocalProcess(run_id, self.package, self.test_name, self.args, os.environ, False, cwd='cwd', is_node=False) 117 118 pm = self.pmon 119 pm.register(process) 120 success = process.start() 121 self.assert_(success, "test failed to start") 122 123 #poll until test terminates or alloted time exceed 124 timeout_t = time.time() + self.time_limit 125 try: 126 while pm.mainthread_spin_once() and process.is_alive(): 127 #test fails on timeout 128 if time.time() > timeout_t: 129 raise roslaunch.launch.RLTestTimeoutException("test max time allotted") 130 time.sleep(0.1) 131 132 except roslaunch.launch.RLTestTimeoutException, e: 133 if self.retry: 134 timeout_failure = True 135 else: 136 raise 137 138 if not timeout_failure: 139 printlog("test [%s] finished"%test_name) 140 else: 141 printlogerr("test [%s] timed out"%test_name) 142 143 # load in test_file 144 if not timeout_failure: 145 self.assert_(os.path.isfile(test_file), "test [%s] did not generate test results"%test_name) 146 printlog("test [%s] results are in [%s]", test_name, test_file) 147 results = rostest.xmlresults.read(test_file, test_name) 148 test_fail = results.num_errors or results.num_failures 149 else: 150 test_fail = True 151 152 if self.retry > 0 and test_fail: 153 self.retry -= 1 154 printlog("test [%s] failed, retrying. Retries left: %s"%(test_name, self.retry)) 155 else: 156 done = True 157 self.results.accumulate(results) 158 printlog("test [%s] results summary: %s errors, %s failures, %s tests", 159 test_name, results.num_errors, results.num_failures, results.num_tests) 160 161 printlog("[ROSTEST] test [%s] done", test_name)
162