Merge lp:~carifio/dotdepends/dotdepends-unittests into lp:dotdepends

Proposed by Mike Carifio
Status: Rejected
Rejected by: Kyle Nitzsche
Proposed branch: lp:~carifio/dotdepends/dotdepends-unittests
Merge into: lp:dotdepends
Diff against target: 384 lines (+153/-57)
5 files modified
Dotdepends/__init__.py (+3/-0)
test/test_Dot.py (+76/-0)
test/test_dotdepends_executable.py (+53/-37)
test/test_template.py (+6/-5)
test/test_template_executable.py (+15/-15)
To merge this branch: bzr merge lp:~carifio/dotdepends/dotdepends-unittests
Reviewer Review Type Date Requested Status
Mike Carifio Pending
Review via email: mp+114513@code.launchpad.net

Description of the change

Response to mfisch review, focused on unittests per kyleN direction.

To post a comment you must log in.
74. By Mike Carifio

Response to LP: #1023564. Starts the unit test process for the Dot object.

75. By Mike Carifio

Dotdepends/__init__.py: Export class 'Dot'
test/test_Dot.py: Use Dotdepends.Dot directly.

Revision history for this message
Kyle Nitzsche (knitzsche) wrote :

1) line 141-44 (and throughout): style guide niggle: (https://dev.launchpad.net/PythonStyleGuide, section Multiline braces) arg/lists like this:
 mydict = {
        'first': 1,
        'second': 2,
        'third': 3,
        }

    mylist = [
        'this is the first line',
        'this is the second line',
        'this is the third line',
        ]

Instead of:
someting(asdn,asdfadf,adfasdf
    asdfadsf,asdfasdf,asdfsadf)

Note the opening and closing braces have no items/args on their lines. This makes for clearer diffs and less awkward line shortening too.

2) Created by 1023897 to track adding more unit tests to Dot.py as occasion permits us.

3) Can we use "not_a_package_12345" instead of "ima_baddy_bad_bad_bad_bad_ohohoh_XXXXXX"

3) are you intentinally writing "iff" (instead of "if") in comments many times

Unmerged revisions

78. By Mike Carifio

test/test_Dot.py:
  - Added test test_no_dot_file(), which expects to receive an exception when creating
    a Dot object with no path.

  - Added test test_no_dot_file_bad_path(), which does the same but this a file pathname.

  - Added -- and then skipped -- test test_no_contents(). This test tries to simulate a file
    with a string using StringIO. Unfortunately, Dot.__init__() expects a pathname, not a file
    handle, so this approach will fail. Need to more completely mock python files, which will
    have to wait.

77. By Mike Carifio

test/test_Dot.py: follow indentation standard for lists.

76. By Mike Carifio

test/test_Dot.py: spelling error

75. By Mike Carifio

Dotdepends/__init__.py: Export class 'Dot'
test/test_Dot.py: Use Dotdepends.Dot directly.

74. By Mike Carifio

Response to LP: #1023564. Starts the unit test process for the Dot object.

73. By Mike Carifio

Retain templates to seed future unit tests.
Right margin now column 78.
Created a utility method run_dotdepends that abstracts away calling the
dotdepends executable from the tests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Dotdepends/__init__.py'
2--- Dotdepends/__init__.py 2012-06-19 19:20:52 +0000
3+++ Dotdepends/__init__.py 2012-07-12 13:57:19 +0000
4@@ -0,0 +1,3 @@
5+import Dot
6+# Allow import Dotdepends; d = Dotdepends.Dot('a/path')
7+__all__ = ['Dot']
8
9=== added file 'test/test_Dot.py'
10--- test/test_Dot.py 1970-01-01 00:00:00 +0000
11+++ test/test_Dot.py 2012-07-12 13:57:19 +0000
12@@ -0,0 +1,76 @@
13+#!/usr/bin/python
14+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 4 -*- ## emacs weenies
15+
16+# Copyright (C) 2012 Canonical, Ltd
17+
18+# Authors:
19+# Mike Carifio <michael.carifio@canonical.com>
20+
21+# This program is free software: you can redistribute it and/or modify
22+# it under the terms of the GNU General Public License as published by
23+# the Free Software Foundation, version 3 of the License.
24+#
25+# This program is distributed in the hope that it will be useful,
26+# but WITHOUT ANY WARRANTY; without even the implied warranty of
27+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+# GNU General Public License for more details.
29+#
30+# You should have received a copy of the GNU General Public License
31+# along with this program. If not, see <http://www.gnu.org/licenses/>.
32+
33+
34+
35+
36+import sys
37+import os
38+import unittest
39+
40+# Point at the objects under test.
41+sys.path.insert(0,
42+ os.path.abspath(
43+ os.path.dirname(os.path.abspath(__file__))
44+ + '/..'))
45+# Point at (possible) supporting test code.
46+sys.path.insert(0,
47+ os.path.dirname(
48+ __file__)) # in case you're running in place
49+
50+
51+#from Dotdepends import Dot
52+import Dotdepends as D
53+
54+class DotTests(unittest.TestCase):
55+ """Test the Dot class"""
56+
57+ # If this set changes in Dot, it should change here too.
58+ bogus_char_set = set(['-', ':', '.', '+'])
59+
60+ def test_always_succeeds(self):
61+ self.assertTrue(True, "tests the test runner")
62+
63+ def test_replacement(self):
64+ for char in self.bogus_char_set:
65+ for token in ['token0', 'with_underscore']:
66+ bad = char + token + char + token + char
67+ good = D.Dot.replacement(bad) # replace bogus chars
68+ for replaced in self.bogus_char_set:
69+ self.assertTrue(good.find(replaced) == -1)
70+
71+ # TODO investigate the right pattern for exception testing
72+ # TODO can python strings act as files?
73+ def test_no_dot_file(self):
74+ """Create Dot from nonexistant dot file raises exception"""
75+ try:
76+ d = D.Dot(None)
77+ self.assertFalse(True, 'exception should have been raised')
78+ except Exception, e: # TODO fix for python3
79+ self.assertTrue(True, 'expecting an exception')
80+
81+
82+# This sequence lets you run the test suite with python directly rather
83+# than with a test runner indirectly.
84+def main():
85+ unittest.main()
86+
87+if __name__ == '__main__':
88+ main()
89
90=== modified file 'test/test_dotdepends_executable.py'
91--- test/test_dotdepends_executable.py 2012-07-03 18:13:33 +0000
92+++ test/test_dotdepends_executable.py 2012-07-12 13:57:19 +0000
93@@ -22,15 +22,14 @@
94 """
95 test_dotdepends_executable -- tests dotdepends
96
97-Unittests for the main program dotdepends (/usr/bin/dotdepends when installed).
98+Unittests for the main program dotdepends (/usr/bin/dotdepends when
99+installed).
100
101 usage: python /path/to/test_dotdepends_executable.py
102- nosetests -v --exe -d /path/to/test ## run all tests, including this one
103+ nosetests -v --exe -d /path/to/test ## run all tests,
104+ including this one
105 """
106
107-
108-
109-
110 import sys
111 import os
112 import subprocess
113@@ -38,7 +37,9 @@
114 import tempfile
115 import shutil
116 import unittest
117-logging.basicConfig(level = logging.DEBUG) ## TODO: how can the test runner pass in args?
118+
119+logging.basicConfig(
120+ level = logging.DEBUG) ## TODO: how can the test runner pass in args?
121
122 # here: is the absolute path of where this test suite is running from.
123 # Find 'here' now *before* you modify sys.path. Otherwise python reports
124@@ -48,17 +49,19 @@
125
126 # Point at the objects under test.
127 sys.path.insert(0,
128- os.path.abspath(os.path.dirname(os.path.abspath(__file__))
129- + '/..'))
130+ os.path.abspath(
131+ os.path.dirname(os.path.abspath(__file__))
132+ + '/..'))
133
134 # Point at (possible) supporting test code.
135-sys.path.insert( 0, os.path.dirname(__file__ ))
136+sys.path.insert(0, os.path.dirname(__file__))
137
138
139 class DotdependsExecutableTestcase(unittest.TestCase):
140 """DotdependsExecutableTestcase
141
142- Run dotdepends on certain packages and with certain switches. This class needs more work.
143+ Run dotdepends on certain packages and with certain switches. This
144+ class needs more work.
145
146 """
147
148@@ -66,13 +69,28 @@
149 working_directory = tempfile.mkdtemp()
150 good_lower_pkg = 'debconf'
151 good_upper_pkg = 'gedit'
152- bad_package = 'ima_baddy'
153+ bad_package = 'ima_baddy_bad_bad_bad_bad_ohohoh_XXXXXX'
154 dotdepends = here + '/../usr/bin/dotdepends'
155
156 def dotdepends_path(self):
157 return self.dotdepends
158
159
160+ def run_dotdepends(self, command):
161+ '''Utility method to run dotdepends executable "in place" as a
162+ subprocess. Callers will test assertions after the call.
163+
164+ :param command: the switches to the dotdepends executable
165+ """
166+ :return: p: the subprocess, stdout, the output and stderr,
167+ the standard error output
168+ '''
169+ p = subprocess.Popen(command, stdout = subprocess.PIPE,
170+ stderr = subprocess.PIPE)
171+ stdout, stderr = p.communicate()
172+ return p, stderr, stdout
173+
174+
175 @classmethod
176 def setUpClass(cls):
177 # Move to the working directory.
178@@ -82,11 +100,11 @@
179
180 @classmethod
181 def tearDownClass(cls):
182- # TODO: remove directory iff all tests pass. Currently removed regardless of test results.
183+ # TODO: remove directory iff all tests pass. Currently removed
184+ # regardless of test results.
185 shutil.rmtree(cls.working_directory)
186
187
188-
189 # Name must be test_<something> so test runner can find them.
190 def test_always_succeeds(self):
191 """Always succeeds. Tests the test runner."""
192@@ -98,11 +116,11 @@
193 logging.debug("dotdepends: " + self.dotdepends_path())
194 self.assertTrue(os.path.exists(self.dotdepends_path()))
195
196+
197 def test_dotdepends_installed(self):
198 """dotdepends -i good_package => 1"""
199- command = [self.dotdepends_path(), '-i', self.good_lower_pkg ]
200- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
201- stdout, stderr = p.communicate()
202+ command = [ self.dotdepends_path(), '-i', self.good_lower_pkg ]
203+ p, stderr, stdout = self.run_dotdepends(command)
204 self.assertEquals(p.returncode, 1)
205 self.assertTrue(stderr.startswith('Error.'))
206 self.assertEqual(len(stdout), 0)
207@@ -110,60 +128,58 @@
208
209 def test_dotdepends_bad_switch(self):
210 """dotdepends --invalid-switch good_pkg => 2"""
211- command = [ self.dotdepends_path(), '--invalid-switch', self.good_lower_pkg ]
212- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
213- stdout, stderr = p.communicate()
214+ command = [ self.dotdepends_path(), '--invalid-switch',
215+ self.good_lower_pkg ]
216+ p, stderr, stdout = self.run_dotdepends(command)
217 self.assertEquals(p.returncode, 2)
218 self.assertEqual(len(stdout), 0)
219
220 def test_dotdepends_mode_depends_switch_i(self):
221- command = [self.dotdepends_path(), '--installed', '-m', 'depends', self.good_lower_pkg ]
222- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
223- stdout, stderr = p.communicate()
224+ command = [ self.dotdepends_path(), '--installed', '-m', 'depends',
225+ self.good_lower_pkg ]
226+ p, stderr, stdout = self.run_dotdepends(command)
227 self.assertEquals(p.returncode, 1)
228 self.assertEqual(len(stdout), 0)
229
230 def test_dotdepends_mode_depends(self):
231- command = [self.dotdepends_path(), '-m', 'depends', self.good_lower_pkg ]
232- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
233- stdout, stderr = p.communicate()
234+ command = [ self.dotdepends_path(), '-m', 'depends',
235+ self.good_lower_pkg ]
236+ p, stderr, stdout = self.run_dotdepends(command)
237 self.assertEquals(p.returncode, 0)
238 self.assertGreater(len(stdout), 0)
239
240
241 def test_dotdepends_analyze(self):
242 command = [ self.dotdepends_path(), self.good_lower_pkg ]
243- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
244- stdout, stderr = p.communicate()
245+ p, stderr, stdout = self.run_dotdepends(command)
246 self.assertEquals(p.returncode, 0)
247 self.assertGreater(len(stdout), 0)
248
249
250 def test_dotdepends_bad_package(self):
251 command = [ self.dotdepends_path(), self.bad_package ]
252- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
253- stdout, stderr = p.communicate()
254+ p, stderr, stdout = self.run_dotdepends(command)
255 self.assertEquals(p.returncode, 1)
256 self.assertEqual(len(stdout), 0)
257- self.assertFalse(os.path.exists(self.working_directory + os.path.sep + self.bad_package ))
258+ self.assertFalse(os.path.exists(
259+ self.working_directory + os.path.sep + self.bad_package))
260
261
262 def test_dotdepends_rdepends(self):
263- command = [ self.dotdepends_path(), '-m', 'rdepends', self.good_upper_pkg ]
264- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
265- stdout, stderr = p.communicate()
266+ command = [ self.dotdepends_path(), '-m', 'rdepends',
267+ self.good_upper_pkg ]
268+ p, stderr, stdout = self.run_dotdepends(command)
269 self.assertEquals(p.returncode, 0)
270 self.assertGreater(len(stdout), 0)
271
272 def test_dotdepends_rdepends_installed_switch(self):
273- command = [ self.dotdepends_path(), '-m', 'rdepends', '-i', self.good_upper_pkg ]
274- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
275- stdout, stderr = p.communicate()
276+ command = [ self.dotdepends_path(), '-m', 'rdepends', '-i',
277+ self.good_upper_pkg ]
278+ p, stderr, stdout = self.run_dotdepends(command)
279 self.assertEquals(p.returncode, 0)
280 self.assertGreater(len(stdout), 0)
281
282
283-
284 # This sequence lets you run the test suite with python directly rather
285 # than with a test runner indirectly.
286 def main():
287
288=== modified file 'test/test_template.py'
289--- test/test_template.py 2012-06-26 15:24:39 +0000
290+++ test/test_template.py 2012-07-12 13:57:19 +0000
291@@ -36,11 +36,13 @@
292
293 # Point at the objects under test.
294 sys.path.insert(0,
295- os.path.abspath(os.path.dirname(os.path.abspath(__file__))
296- + '/..'))
297+ os.path.abspath(
298+ os.path.dirname(os.path.abspath(__file__))
299+ + '/..'))
300 # Point at (possible) supporting test code.
301-sys.path.insert( 0,
302- os.path.dirname(__file__ ) ) # in case you're running in place
303+sys.path.insert(0,
304+ os.path.dirname(
305+ __file__)) # in case you're running in place
306
307
308 # Name must be <Something>Tests so test runner can find it
309@@ -59,7 +61,6 @@
310 self.skipTest("skipping at runtime")
311
312
313-
314 # This sequence lets you run the test suite with python directly rather
315 # than with a test runner indirectly.
316 def main():
317
318=== modified file 'test/test_template_executable.py'
319--- test/test_template_executable.py 2012-07-02 17:37:34 +0000
320+++ test/test_template_executable.py 2012-07-12 13:57:19 +0000
321@@ -39,22 +39,25 @@
322
323 # Point at the objects under test.
324 sys.path.insert(0,
325- os.path.abspath(os.path.dirname(os.path.abspath(__file__))
326- + '/..'))
327+ os.path.abspath(os.path.dirname(os.path.abspath(__file__))
328+ + '/..'))
329 # Point at (possible) supporting test code.
330-sys.path.insert( 0,
331- os.path.dirname(__file__ ) ) # in case you're running in place
332-
333-me, _ = os.path.splitext(os.path.basename(__file__)) # name of this file, less .py
334-
335-logging.basicConfig(level = logging.DEBUG) ## TODO: how can the test runner pass in args?
336+sys.path.insert(0,
337+ os.path.dirname(__file__)) # in case you're running in place
338+
339+me, _ = os.path.splitext(
340+ os.path.basename(__file__)) # name of this file, less .py
341+
342+logging.basicConfig(
343+ level = logging.DEBUG) ## TODO: how can the test runner pass in args?
344
345 # Name must be <Something>Tests so test runner can find it
346 class TemplateExecutableTests(unittest.TestCase):
347 """Describe the tests here"""
348
349 # working_directory is a resource supporting the test
350- # Create it before the tests are run. Remove it after the tests are run iff
351+ # Create it before the tests are run. Remove it after the tests are run
352+ # iff
353 # all tests succeed.
354 working_directory = mkdtemp()
355
356@@ -70,7 +73,6 @@
357 shutil.rmtree(cls.working_directory)
358
359
360-
361 # Name must be test_<something> so test runner can find them.
362 def test_always_succeeds(self):
363 """Always succeeds. Tests the test runner."""
364@@ -86,17 +88,15 @@
365 self.skipTest("skipping at runtime")
366
367 def test_that_runs_an_external_executable(self):
368- command = ['ls', '-la', '/']
369- p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
370+ command = [ 'ls', '-la', '/' ]
371+ p = subprocess.Popen(command, stdout = subprocess.PIPE,
372+ stderr = subprocess.PIPE)
373 stdout, stderr = p.communicate()
374 self.assertEquals(p.returncode, 0) # exit status 0
375 self.assertEqual(stderr, '') # no errors reported to stderr
376 self.assertGreater(len(stdout), 0) # should be some output
377
378
379-
380-
381-
382 # This sequence lets you run the test suite with python directly rather
383 # than with a test runner indirectly.
384 def main():

Subscribers

People subscribed via source and target branches

to all changes: