1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 from __future__ import with_statement
36
37 """
38 Interface for using rostest from other Python code as well as running
39 Python unittests with additional reporting mechanisms and rosbuild
40 (CMake) integration.
41 """
42
43 import sys
44
45 XML_OUTPUT_FLAG = '--gtest_output=xml:'
46
48 """
49 Predicate to check whether or not master think subscriber_id
50 subscribes to topic.
51 @return: True if still register as a subscriber
52 @rtype: bool
53 """
54 import roslib.scriptutil as scriptutil
55 return scriptutil.is_subscriber(topic, subscriber_id)
56
58 """
59 Predicate to check whether or not master think publisher_id
60 publishes topic.
61 @return: True if still register as a publisher
62 @rtype: bool
63 """
64 import roslib.scriptutil as scriptutil
65 return scriptutil.is_publisher(topic, publisher_id)
66
67 -def rosrun(package, test_name, test, sysargs=None):
68 """
69 Run a rostest/unittest-based integration test.
70
71 @param package: name of package that test is in
72 @type package: str
73 @param test_name: name of test that is being run
74 @type test_name: str
75 @param test: test class
76 @type test: unittest.TestCase
77 @param sysargs: command-line args. If not specified, this defaults to sys.argv. rostest
78 will look for the --text and --gtest_output parameters
79 @type sysargs: list
80 """
81 if sysargs is None:
82
83 import sys
84 sysargs = sys.argv
85
86
87 result_file = None
88 for arg in sysargs:
89 if arg.startswith(XML_OUTPUT_FLAG):
90 result_file = arg[len(XML_OUTPUT_FLAG):]
91 text_mode = '--text' in sysargs
92 coverage_mode = '--cov' in sysargs
93 if coverage_mode:
94 _start_coverage(package)
95
96
97 from rostestutil import createXMLRunner, printSummary
98 import unittest
99 import rospy
100
101 suite = unittest.TestLoader().loadTestsFromTestCase(test)
102 if text_mode:
103 result = unittest.TextTestRunner(verbosity=2).run(suite)
104 else:
105 result = createXMLRunner(package, test_name, result_file).run(suite)
106 if coverage_mode:
107 _stop_coverage(package)
108 printSummary(result)
109
110
111 rospy.signal_shutdown('test complete')
112 if not result.wasSuccessful():
113 import sys
114 sys.exit(1)
115
116
117 run = rosrun
118
119 -def unitrun(package, test_name, test, sysargs=None, coverage_packages=None):
120 """
121 Wrapper routine from running python unitttests with
122 JUnit-compatible XML output. This is meant for unittests that do
123 not not need a running ROS graph (i.e. offline tests only).
124
125 This enables JUnit-compatible test reporting so that
126 test results can be reported to higher-level tools.
127
128 @param package: name of ROS package that is running the test
129 @type package: str
130 @param coverage_packages: list of Python package to compute coverage results for. Defaults to package
131 @type coverage_packages: [str]
132 """
133 if sysargs is None:
134
135 import sys
136 sysargs = sys.argv
137
138 import unittest
139
140 if coverage_packages is None:
141 coverage_packages = [package]
142
143
144 result_file = None
145 for arg in sysargs:
146 if arg.startswith(XML_OUTPUT_FLAG):
147 result_file = arg[len(XML_OUTPUT_FLAG):]
148 text_mode = '--text' in sysargs
149
150 coverage_mode = '--cov' in sysargs or '--covhtml' in sysargs
151 if coverage_mode:
152 _start_coverage(coverage_packages)
153
154
155 from rostestutil import createXMLRunner, printSummary
156
157 suite = unittest.TestLoader().loadTestsFromTestCase(test)
158 if text_mode:
159 result = unittest.TextTestRunner(verbosity=2).run(suite)
160 else:
161 result = createXMLRunner(package, test_name, result_file).run(suite)
162 if coverage_mode:
163 cov_html_dir = 'covhtml' if '--covhtml' in sysargs else None
164 _stop_coverage(coverage_packages, html=cov_html_dir)
165 printSummary(result)
166
167 if not result.wasSuccessful():
168 import sys
169 sys.exit(1)
170
171
172 _cov = None
174 global _cov
175 try:
176 import coverage
177 try:
178 _cov = coverage.coverage()
179
180 _cov.load()
181 _cov.start()
182 except coverage.CoverageException:
183 print >> sys.stderr, "WARNING: you have an older version of python-coverage that is not support. Please update to the version provided by 'easy_install coverage'"
184 except ImportError, e:
185 print >> sys.stderr, """WARNING: cannot import python-coverage, coverage tests will not run.
186 To install coverage, run 'easy_install coverage'"""
187 try:
188
189 for package in packages:
190 if package in sys.modules:
191 reload(sys.modules[package])
192 except ImportError, e:
193 print >> sys.stderr, "WARNING: cannot import '%s', will not generate coverage report"%package
194 return
195
197 """
198 @param packages: list of packages to generate coverage reports for
199 @type packages: [str]
200 @param html: (optional) if not None, directory to generate html report to
201 @type html: str
202 """
203 if _cov is None:
204 return
205 import sys, os
206 try:
207 _cov.stop()
208
209 _cov.save()
210
211
212
213
214
215 if os.path.exists('.coverage-modules'):
216 with open('.coverage-modules','r') as f:
217 all_packages = set([x for x in f.read().split('\n') if x.strip()] + packages)
218 else:
219 all_packages = set(packages)
220 with open('.coverage-modules','w') as f:
221 f.write('\n'.join(all_packages)+'\n')
222
223 try:
224
225 all_mods = []
226
227
228 for package in packages:
229 pkg = __import__(package)
230 m = [v for v in sys.modules.values() if v and v.__name__.startswith(package)]
231 all_mods.extend(m)
232
233
234 _cov.report(m, show_missing=0)
235 for mod in m:
236 res = _cov.analysis(mod)
237 print "\n%s:\nMissing lines: %s"%(res[0], res[3])
238
239 if html:
240
241 print "="*80+"\ngenerating html coverage report to %s\n"%html+"="*80
242 _cov.html_report(all_mods, directory=html)
243 except ImportError, e:
244 print >> sys.stderr, "WARNING: cannot import '%s', will not generate coverage report"%package
245 except ImportError, e:
246 print >> sys.stderr, """WARNING: cannot import python-coverage, coverage tests will not run.
247 To install coverage, run 'easy_install coverage'"""
248
249
250
252
253 from rostest.rostest_main import rostestmain as _main
254 _main()
255