Merge lp:~mbp/testscenarios/module-scenarios into lp:~testtools-committers/testscenarios/trunk

Proposed by Martin Pool
Status: Merged
Merged at revision: 19
Proposed branch: lp:~mbp/testscenarios/module-scenarios
Merge into: lp:~testtools-committers/testscenarios/trunk
Diff against target: 140 lines (+87/-2)
4 files modified
NEWS (+6/-0)
README (+29/-0)
lib/testscenarios/scenarios.py (+35/-1)
lib/testscenarios/tests/test_scenarios.py (+17/-1)
To merge this branch: bzr merge lp:~mbp/testscenarios/module-scenarios
Reviewer Review Type Date Requested Status
Robert Collins Pending
Review via email: mp+80287@code.launchpad.net

This proposal supersedes a proposal from 2011-07-08.

Description of the change

This separates out something we do in bzr, which is to multiply tests by both Python and Pyrex/C implementations of the same interface.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote : Posted in a previous version of this proposal

For some reason this has generated a merge proposal with a bunch of conflicts :(

Revision history for this message
Martin Pool (mbp) wrote :

conflicts fixed (at least locally)

Revision history for this message
Martin Pool (mbp) wrote :

robert could you review this please?

Revision history for this message
Robert Collins (lifeless) wrote :

I think this is good but IIRC John has a desire to sometimes require that the other implementation is present. Perhaps rather than eliding implements we cannot import, we emit synthetic skips for them, would permit the test runner to decide on policy (e.g. to fail, or to just report the test as skipped).

What do you think?

Other than that this seems very nice.

Revision history for this message
Martin Pool (mbp) wrote :

On 29 November 2011 13:13, Robert Collins <email address hidden> wrote:
> I think this is good but IIRC John has a desire to sometimes require that the other implementation is present. Perhaps rather than eliding implements we cannot import, we emit synthetic skips for them, would permit the test runner to decide on policy (e.g. to fail, or to just report the test as skipped).

I think that's reasonable to want. Also, squashing ImportError
altogether is probably too likely to hide real problems.

Revision history for this message
Martin Pool (mbp) wrote :

On consideration, although those improvements would be useful, I think
we could land this and add them as enhancements when they're wanted -
maybe when we change bzr to use this.

Revision history for this message
Robert Collins (lifeless) wrote :

On Tue, Nov 29, 2011 at 7:19 PM, Martin Pool <email address hidden> wrote:
> On consideration, although those improvements would be useful, I think
> we could land this and add them as enhancements when they're wanted -
> maybe when we change bzr to use this.

I'd really rather not be hiding ImportError at all - It seems to me
all users are going to want that, so rather than changing the
behaviour in a later release, I'd rather we tweak this now.

Revision history for this message
Robert Collins (lifeless) wrote :

I think this needs a (shallow) patch to testtools to make it trivial to wrap a test with a skip.

Revision history for this message
Robert Collins (lifeless) wrote :
Revision history for this message
Martin Pool (mbp) wrote :

Thanks!
On Apr 4, 2012 8:05 PM, <email address hidden> wrote:

> The proposal to merge lp:~mbp/testscenarios/module-scenarios into
> lp:testscenarios has been updated.
>
> Status: Needs review => Merged
>
> For more details, see:
> https://code.launchpad.net/~mbp/testscenarios/module-scenarios/+merge/80287
> --
> https://code.launchpad.net/~mbp/testscenarios/module-scenarios/+merge/80287
> You are the owner of lp:~mbp/testscenarios/module-scenarios.
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2010-10-12 06:57:23 +0000
+++ NEWS 2011-10-25 04:00:30 +0000
@@ -9,6 +9,12 @@
90.290.2
10~~~10~~~
1111
12NEW FEATURES:
13
14* New function ``per_module_scenarios`` for tests that should be applied across
15 multiple modules providing the same interface, some of which may not be
16 available at run time. (Martin Pool)
17
12CHANGES:18CHANGES:
1319
14* Adjust the cloned tests ``shortDescription`` if one is present. (Ben Finney)20* Adjust the cloned tests ``shortDescription`` if one is present. (Ben Finney)
1521
=== modified file 'README'
--- README 2010-10-12 06:57:23 +0000
+++ README 2011-10-25 04:00:30 +0000
@@ -258,6 +258,35 @@
258selection.258selection.
259259
260260
261Generating Scenarios
262====================
263
264Some functions (currently one :-) are available to ease generation of scenario
265lists for common situations.
266
267Testing Per Implementation Module
268+++++++++++++++++++++++++++++++++
269
270It is reasonably common to have multiple Python modules that provide the same
271capabilities and interface, and to want apply the same tests to all of them.
272
273In some cases, not all of the statically defined implementations will be able
274to be used in a particular testing environment. For example, there may be both
275a C and a pure-Python implementation of a module. You want to test the C
276module if it can be loaded, but also to have the tests pass if the C module has
277not been compiled.
278
279The ``per_module_scenarios`` function generates a scenario for each named
280module, omitting those that raise an ``ImportError``. For each test object,
281the implementation to be tested is installed into a given attribute.
282
283Note that for the test to be valid, all access to the module under test must go
284through the relevant attribute of the test object. If one of the
285implementations is also directly imported by the test module or any other,
286testscenarios will not magically stop it being used.
287
288
289
261Advice on Writing Scenarios290Advice on Writing Scenarios
262===========================291===========================
263292
264293
=== modified file 'lib/testscenarios/scenarios.py'
--- lib/testscenarios/scenarios.py 2010-10-12 06:57:23 +0000
+++ lib/testscenarios/scenarios.py 2011-10-25 04:00:30 +0000
@@ -2,7 +2,7 @@
2# dependency injection ('scenarios') by tests.2# dependency injection ('scenarios') by tests.
3#3#
4# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>4# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
5# Copyright (c) 2010 Martin Pool <mbp@sourcefrog.net>5# Copyright (c) 2010, 2011 Martin Pool <mbp@sourcefrog.net>
6# 6#
7# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause7# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
8# license at the users choice. A copy of both licenses are available in the8# license at the users choice. A copy of both licenses are available in the
@@ -129,3 +129,37 @@
129 scenario_parameters.update(parameter)129 scenario_parameters.update(parameter)
130 result.append((scenario_name, scenario_parameters))130 result.append((scenario_name, scenario_parameters))
131 return result131 return result
132
133
134def per_module_scenarios(attribute_name, modules):
135 """Generate scenarios for available implementation modules.
136
137 This is typically used when there is a subsystem implemented, for
138 example, in both Python and C, and we want to apply the same tests to
139 both, but the C module may sometimes not be available.
140
141 Note: if the module can't be loaded, it's silently omitted from
142 testing.
143
144 :param attribute_name: A name to be set in the scenario parameter
145 dictionary (and thence onto the test instance) pointing to the
146 implementation module for this scenario.
147
148 :param modules: An iterable of (short_name, module_name), where
149 the short name is something like 'python' to put in the
150 scenario name, and the long name is a fully-qualified Python module
151 name.
152 """
153 scenarios = []
154 for short_name, module_name in modules:
155 try:
156 mod = __import__(module_name, {}, {}, [''])
157 except ImportError:
158 # TODO: optionally pass this back through a callback, so it can be
159 # logged etc?
160 pass
161 else:
162 scenarios.append((
163 short_name,
164 {attribute_name: mod}))
165 return scenarios
132166
=== modified file 'lib/testscenarios/tests/test_scenarios.py'
--- lib/testscenarios/tests/test_scenarios.py 2010-10-12 06:57:23 +0000
+++ lib/testscenarios/tests/test_scenarios.py 2011-10-25 04:00:30 +0000
@@ -2,7 +2,7 @@
2# dependency injection ('scenarios') by tests.2# dependency injection ('scenarios') by tests.
3#3#
4# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>4# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
5# Copyright (c) 2010 Martin Pool <mbp@sourcefrog.net>5# Copyright (c) 2010, 2011 Martin Pool <mbp@sourcefrog.net>
6# 6#
7# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause7# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
8# license at the users choice. A copy of both licenses are available in the8# license at the users choice. A copy of both licenses are available in the
@@ -239,3 +239,19 @@
239 self.assertEqual(239 self.assertEqual(
240 'a,a,a,a',240 'a,a,a,a',
241 scenarios[0][0])241 scenarios[0][0])
242
243
244class TestPerModuleScenarios(testtools.TestCase):
245
246 def test_per_module_scenarios(self):
247 """Generate scenarios for available modules"""
248 s = testscenarios.scenarios.per_module_scenarios(
249 'the_module', [
250 ('Python', 'testscenarios'),
251 ('unittest', 'unittest'),
252 ('nonexistent', 'nonexistent'),
253 ])
254 self.assertEqual(s, [
255 ('Python', {'the_module': testscenarios}),
256 ('unittest', {'the_module': unittest}),
257 ])

Subscribers

People subscribed via source and target branches