[apparmor] [patch] add better loop support to common_test.py

Steve Beattie steve at nxnw.org
Tue Mar 31 08:36:10 UTC 2015


Hi,

Sorry for the delay in reviewing.

On Fri, Mar 06, 2015 at 11:57:11PM +0100, Christian Boltz wrote:
> It turned out that adding
>     from apparmor.aa import AppArmorException
> in test-*.py explodes with
> 
> Traceback (most recent call last):
>   File "test-example.py", line 45, in <module>
>     setup_all_tests()
>   File "/home/cb/apparmor/HEAD-clean/utils/test/common_test.py", line 58, in setup_all_tests
>     if inspect.isclass(obj) and (isinstance(obj(), unittest.TestCase)):
> TypeError: __init__() missing 1 required positional argument: 'value'
> 
> The reason for this is that AppArmorException __init__() has an additional
> parameter. This means we have to wrap "obj()" in try/except. Fortunately
> this affects only non-test classes :-)
> 
> Since Seth seems to be out of counter-arguments for 
> 12-test-loop-simplify.diff, I also merged it into this patch.
> (It also affects another patch, which I'll resend in a minute.)
> 
> 
> Here's v3, this time with the number included in the filename ;-)

Unfortunately, this doesn't appear to work under python2:

  $ PYTHONPATH=.. python2 test-example.py
  Traceback (most recent call last):
    File "test-example.py", line 44, in <module>
      setup_all_tests()
    File "/home/steve/bzr/apparmor-master/utils/test/common_test.py", line 60, in setup_all_tests
      obj_instance = obj() # will fail for (non-test) classes with additional __init__ parameters
    File "/usr/lib/python2.7/unittest/case.py", line 189, in __init__
      (self.__class__, methodName))
  ValueError: no such test method in <class 'common_test.AATest'>: runTest

I suspect this has to do with the differences in how objects are
internally implemented between python 2 and python 3.

And while python 3 has gotten wider support and I would like to
eventually drop support for python 2.7, I don't think we can justify
doing so quite yet.

> [ 07-common_test_better_loop_support.diff ]
> 
> === modified file 'utils/test/common_test.py'
> --- utils/test/common_test.py   2014-11-06 20:32:49 +0000
> +++ utils/test/common_test.py   2015-03-03 23:37:48 +0000
> @@ -1,5 +1,6 @@
>  # ----------------------------------------------------------------------
>  #    Copyright (C) 2013 Kshitij Gupta <kgupta8592 at gmail.com>
> +#    Copyright (C) 2015 Christian Boltz <apparmor at cboltz.de>
>  #
>  #    This program is free software; you can redistribute it and/or
>  #    modify it under the terms of version 2 of the GNU General Public
> @@ -12,6 +13,8 @@
>  #
>  # ----------------------------------------------------------------------
>  import unittest
> +import inspect
>  import os
>  import re
> +import sys
>  
> @@ -34,6 +36,10 @@
>      #    print("Please press the Y button on the keyboard.")
>      #    self.assertEqual(apparmor.common.readkey().lower(), 'y', 'Error reading key from shell!')
>  
> +
> +class AATest(unittest.TestCase):
> +    tests = []
> +
>  class AAParseTest(unittest.TestCase):
>      parse_function = None
>  
> @@ -44,6 +50,37 @@
>              'parse object %s returned "%s", expected "%s"' \
>              %(self.parse_function.__doc__, parsed.serialize(), rule))
>  
> +
> +def setup_all_tests():
> +    '''call setup_tests_loop() for each class in module_name'''
> +    for name, obj in inspect.getmembers(sys.modules['__main__']):
> +        if inspect.isclass(obj):
> +            try:
> +                obj_instance = obj() # will fail for (non-test) classes with additional __init__ parameters
> +            except TypeError:
> +                obj_instance = None
> +            if obj_instance and isinstance(obj_instance, unittest.TestCase):
> +                setup_tests_loop(obj)
> +
> +def setup_tests_loop(test_class):
> +    '''Create tests in test_class using test_class.tests and self._run_test()
> +
> +    test_class.tests should be tuples of (test_data, expected_results)
> +    test_data and expected_results can be of any type as long as test_class._run_test()
> +    know how to handle them.
> +
> +    A typical definition for _run_test() is:
> +        def test_class._run_test(self, test_data, expected)
> +        '''
> +
> +    for (i, (test_data, expected)) in enumerate(test_class.tests):
> +        def stub_test(self, test_data=test_data, expected=expected):
> +            self._run_test(test_data, expected)
> +
> +        stub_test.__doc__ = "test '%s'" % (test_data)
> +        setattr(test_class, 'test_%d' % (i), stub_test)
> +
> +
>  def setup_regex_tests(test_class):
>      '''Create tests in test_class using test_class.tests and AAParseTest._test_parse_rule()
>  
> 
> === added file 'utils/test/test-example.py'
> --- utils/test/test-example.py  1970-01-01 00:00:00 +0000
> +++ utils/test/test-example.py  2015-03-03 21:05:18 +0000
> @@ -0,0 +1,45 @@
> +#! /usr/bin/env python
> +# ------------------------------------------------------------------
> +#
> +#    Copyright (C) 2015 Christian Boltz <apparmor at cboltz.de>
> +#
> +#    This program is free software; you can redistribute it and/or
> +#    modify it under the terms of version 2 of the GNU General Public
> +#    License published by the Free Software Foundation.
> +#
> +# ------------------------------------------------------------------
> +
> +import unittest
> +from common_test import AATest, setup_all_tests
> +
> +class TestFoo(AATest):
> +    tests = [
> +        (0,  0 ),
> +        (42, 42),
> +    ]
> +
> +    def _run_test(self, params, expected):
> +        self.assertEqual(params, expected)
> +
> +class TestBar(AATest):
> +    tests = [
> +        ('a', 'foo'),
> +        ('b', 'bar'),
> +        ('c', 'baz'),
> +    ]
> +
> +    def _run_test(self, params, expected):
> +        self.assertNotEqual(params, expected)
> +
> +    def testAdditionalBarTest(self):
> +        self.assertEqual(1, 1)
> +
> +class TestBaz(AATest):
> +    def test_Baz_only_one_test(self):
> +        self.assertEqual("baz", "baz")
> +
> +
> +
> +if __name__ == '__main__':
> +    setup_all_tests()
> +    unittest.main(verbosity=2)



-- 
Steve Beattie
<sbeattie at ubuntu.com>
http://NxNW.org/~steve/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20150331/c376a434/attachment.pgp>


More information about the AppArmor mailing list