homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author brett.cannon
Recipients Arfrever, brett.cannon, eli.bendersky, eric.snow, ezio.melotti, pitrou
Date 2013年01月27日.19:09:33
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1359313773.56.0.425694552304.issue17037@psf.upfronthosting.co.za>
In-reply-to
Content
OK, let's take a step back here and look at what exactly we are trying to simplify (which is now the updated example in PEP 399)::
 from test.support import import_fresh_module
 import unittest
 c_heapq = import_fresh_module('heapq', fresh=['_heapq'])
 py_heapq = import_fresh_module('heapq', blocked=['_heapq'])
 class ExampleTest:
 def test_example(self):
 self.assertTrue(hasattr(self.module, 'heapify'))
 class PyExampleTest(ExampleTest, unittest.TestCase):
 module = py_heapq
 @unittest.skipUnless(c_heapq, 'requires the C _heapq module')
 class CExampleTest(ExampleTest, unittest.TestCase):
 module = c_heapq
 if __name__ == '__main__':
 unittest.main()
Ignoring the unittest.main() boilerplate, we have two import_fresh_module() calls and the creation of two subclasses of ExampleTest, both of which inherit from unittest.TestCase and one of which is skipped if the acceleration code is lacking. So there is some boilerplate. The question is whether a solution be made that isn't too magical to minimize this code.
In my head I see this becoming something more like::
 from test.support import PEP399Tests
 pep399_tests = PEP399Tests('heapq', '_heapq')
 class ExampleTest:
 def test_example(self):
 self.assertTrue(hasattr(self.heapq, 'heapify'))
 PyExampleTest, CExampleTest = pep399_tests.create_test_cases(ExampleTest)
 if __name__ == '__main__':
 unittest.main()
This would cut out the import_fresh_module() calls (which don't need to be injected globally as you should be accessing the code through the test class' attribute storing the module and if you don't care what version you get you just do a standard imoprt), remembering to subclass unittest.TestCase, and to skip the accelerated version of the tests if it isn't needed. Basically it goes from 7 lines to 2 with not repetitious lines. You could make this a decorator, but honestly it's the same number of lines without the magic of mucking with a module's globals by getting at them through sys.modules (the decorator really only saves you from typing the variable names to hold the new test classes and the test class argument to begin with).
And the implementation should be relatively straight-forward (thanks to Eric having done most of the thinking on what needs to happen)::
 class PEP399Tests:
 # Using keyword-only arguments you could go as far as allowing for
 # customizing the attribute name to set, class name prefixes, etc.
 def __init__(module_name, *accelerated_names):
 self.module_name = module_name
 self.py_module = import_fresh_module(module_name, fresh=accelerated_names)
 self.accelerated_module = import_fresh_module(module_name, block=accelerated_names)
 def create_test_cases(self, test_class):
 class PyTestCase(test_class, unittest.TestCase): pass
 PyTestCase.__name__ = 'Py' + test_class.__name__
 setattr(PyTestCase, self.module_name, self.py_module)
 if self.accelerated_module is None:
 AcceleratedTestCase = None
 else:
 class AcceleratedTestCase(test_class, unittest.TestCase): pass
 AcceleratedTestCase.__name__ = 'Accelerated' + test_class.__name__
 setattr(AcceleratedTestCase, self.module_name, self.accelerated_module)
 return PyTestCase, AcceleratedTestCase
Does this approach seem more reasonable to people in terms of cutting down boilerplate without being too magical?
History
Date User Action Args
2013年01月27日 19:09:33brett.cannonsetrecipients: + brett.cannon, pitrou, ezio.melotti, Arfrever, eli.bendersky, eric.snow
2013年01月27日 19:09:33brett.cannonsetmessageid: <1359313773.56.0.425694552304.issue17037@psf.upfronthosting.co.za>
2013年01月27日 19:09:33brett.cannonlinkissue17037 messages
2013年01月27日 19:09:33brett.cannoncreate

AltStyle によって変換されたページ (->オリジナル) /