Browse code

Switch tests to pytest and ansible-test.

- Replace nose usage with pytest.
- Remove legacy Shippable integration.sh.
- Update Makefile to use pytest and ansible-test.
- Convert most yield unit tests to pytest parametrize.

Matt Clay authored on 2017/01/12 05:03:26
Showing 13 changed files
... ...
@@ -98,22 +98,30 @@ RPMNVR = "$(NAME)-$(VERSION)-$(RPMRELEASE)$(RPMDIST)"
98 98
 MOCK_BIN ?= mock
99 99
 MOCK_CFG ?=
100 100
 
101
-NOSETESTS ?= nosetests
101
+# ansible-test parameters
102
+ANSIBLE_TEST ?= test/runner/ansible-test
103
+TEST_FLAGS ?=
102 104
 
103
-NOSETESTS3 ?= nosetests-3.5
105
+# ansible-test units parameters (make test / make test-py3)
106
+PYTHON_VERSION ?= $(shell python2 -c 'import sys; print("%s.%s" % sys.version_info[:2])')
107
+PYTHON3_VERSION ?= $(shell python3 -c 'import sys; print("%s.%s" % sys.version_info[:2])')
108
+
109
+# ansible-test integration parameters (make integration)
110
+IMAGE ?= centos7
111
+TARGET ?=
104 112
 
105 113
 ########################################################
106 114
 
107 115
 all: clean python
108 116
 
109 117
 tests:
110
-	PYTHONPATH=./lib $(NOSETESTS) -d -w test/units -v --with-coverage --cover-package=ansible --cover-branches --cover-erase -e test_os_server
118
+	$(ANSIBLE_TEST) units -v --python $(PYTHON_VERSION) $(TEST_FLAGS)
111 119
 
112 120
 tests-py3:
113
-	PYTHONPATH=./lib $(NOSETESTS3) -d -w test/units -v --with-coverage --cover-package=ansible --cover-branches --cover-erase -e test_os_server
121
+	$(ANSIBLE_TEST) units -v --python $(PYTHON3_VERSION) $(TEST_FLAGS)
114 122
 
115 123
 integration:
116
-	test/utils/shippable/integration.sh
124
+	$(ANSIBLE_TEST) integration -v --docker $(IMAGE) $(TARGET) $(TEST_FLAGS)
117 125
 
118 126
 authors:
119 127
 	sh hacking/authors.sh
... ...
@@ -17,7 +17,7 @@ and do not wish to install them from your operating system package manager, you
17 17
 can install them from pip
18 18
 
19 19
     $ easy_install pip               # if pip is not already available
20
-    $ pip install pyyaml jinja2 nose passlib pycrypto
20
+    $ pip install pyyaml jinja2 nose pytest passlib pycrypto
21 21
 
22 22
 From there, follow ansible instructions on docs.ansible.com as normal.
23 23
 
... ...
@@ -14,3 +14,4 @@ six
14 14
 unittest2
15 15
 mock
16 16
 nose
17
+pytest
... ...
@@ -12,7 +12,7 @@ mock interfaces rather than producing side effects.
12 12
 
13 13
 Playbook engine code is better suited for integration tests.
14 14
 
15
-Requirements: `sudo pip install paramiko PyYAML jinja2 httplib2 passlib nose mock`
15
+Requirements: `sudo pip install paramiko PyYAML jinja2 httplib2 passlib nose pytest mock`
16 16
 
17 17
 integration
18 18
 -----------
... ...
@@ -1,121 +1,100 @@
1
-import collections
2
-import os
3
-import re
4
-
5
-
6
-from nose.tools import eq_
7
-try:
8
-    from nose.tools import assert_raises_regexp
9
-except ImportError:
10
-    from ansible.compat.six import string_types
11
-    # Python < 2.7
12
-    def assert_raises_regexp(expected, regexp, callable, *a, **kw):
13
-        try:
14
-            callable(*a, **kw)
15
-        except expected as e:
16
-            if isinstance(regexp, string_types):
17
-                regexp = re.compile(regexp)
18
-            if not regexp.search(str(e)):
19
-                raise Exception('"%s" does not match "%s"' %
20
-                                (regexp.pattern, str(e)))
21
-        else:
22
-            if hasattr(expected,'__name__'): excName = expected.__name__
23
-            else: excName = str(expected)
24
-            raise AssertionError("%s not raised" % excName)
25
-
26
-from ansible.compat.tests import mock
1
+import pytest
27 2
 
28 3
 from ansible.module_utils.database import (
29 4
     pg_quote_identifier,
30 5
     SQLParseError,
31 6
 )
32 7
 
8
+# These are all valid strings
9
+# The results are based on interpreting the identifier as a table name
10
+VALID = {
11
+    # User quoted
12
+    '"public.table"': '"public.table"',
13
+    '"public"."table"': '"public"."table"',
14
+    '"schema test"."table test"': '"schema test"."table test"',
15
+
16
+    # We quote part
17
+    'public.table': '"public"."table"',
18
+    '"public".table': '"public"."table"',
19
+    'public."table"': '"public"."table"',
20
+    'schema test.table test': '"schema test"."table test"',
21
+    '"schema test".table test': '"schema test"."table test"',
22
+    'schema test."table test"': '"schema test"."table test"',
23
+
24
+    # Embedded double quotes
25
+    'table "test"': '"table ""test"""',
26
+    'public."table ""test"""': '"public"."table ""test"""',
27
+    'public.table "test"': '"public"."table ""test"""',
28
+    'schema "test".table': '"schema ""test"""."table"',
29
+    '"schema ""test""".table': '"schema ""test"""."table"',
30
+    '"""wat"""."""test"""': '"""wat"""."""test"""',
31
+    # Sigh, handle these as well:
32
+    '"no end quote': '"""no end quote"',
33
+    'schema."table': '"schema"."""table"',
34
+    '"schema.table': '"""schema"."table"',
35
+    'schema."table.something': '"schema"."""table"."something"',
36
+
37
+    # Embedded dots
38
+    '"schema.test"."table.test"': '"schema.test"."table.test"',
39
+    '"schema.".table': '"schema."."table"',
40
+    '"schema."."table"': '"schema."."table"',
41
+    'schema.".table"': '"schema".".table"',
42
+    '"schema".".table"': '"schema".".table"',
43
+    '"schema.".".table"': '"schema.".".table"',
44
+    # These are valid but maybe not what the user intended
45
+    '."table"': '".""table"""',
46
+    'table.': '"table."',
47
+}
48
+
49
+INVALID = {
50
+    ('test.too.many.dots', 'table'): 'PostgreSQL does not support table with more than 3 dots',
51
+    ('"test.too".many.dots', 'database'): 'PostgreSQL does not support database with more than 1 dots',
52
+    ('test.too."many.dots"', 'database'): 'PostgreSQL does not support database with more than 1 dots',
53
+    ('"test"."too"."many"."dots"', 'database'): "PostgreSQL does not support database with more than 1 dots",
54
+    ('"test"."too"."many"."dots"', 'schema'): "PostgreSQL does not support schema with more than 2 dots",
55
+    ('"test"."too"."many"."dots"', 'table'): "PostgreSQL does not support table with more than 3 dots",
56
+    ('"test"."too"."many"."dots"."for"."column"', 'column'): "PostgreSQL does not support column with more than 4 dots",
57
+    ('"table "invalid" double quote"', 'table'): 'User escaped identifiers must escape extra quotes',
58
+    ('"schema "invalid"""."table "invalid"', 'table'): 'User escaped identifiers must escape extra quotes',
59
+    ('"schema."table"', 'table'): 'User escaped identifiers must escape extra quotes',
60
+    ('"schema".', 'table'): 'Identifier name unspecified or unquoted trailing dot',
61
+}
62
+
63
+HOW_MANY_DOTS = (
64
+    ('role', 'role', '"role"',
65
+     'PostgreSQL does not support role with more than 1 dots'),
66
+    ('db', 'database', '"db"',
67
+     'PostgreSQL does not support database with more than 1 dots'),
68
+    ('db.schema', 'schema', '"db"."schema"',
69
+     'PostgreSQL does not support schema with more than 2 dots'),
70
+    ('db.schema.table', 'table', '"db"."schema"."table"',
71
+     'PostgreSQL does not support table with more than 3 dots'),
72
+    ('db.schema.table.column', 'column', '"db"."schema"."table"."column"',
73
+     'PostgreSQL does not support column with more than 4 dots'),
74
+)
75
+
76
+VALID_QUOTES = ((test, VALID[test]) for test in VALID)
77
+INVALID_QUOTES = ((test[0], test[1], INVALID[test]) for test in INVALID)
78
+
79
+
80
+@pytest.mark.parametrize("identifier, quoted_identifier", VALID_QUOTES)
81
+def test_valid_quotes(identifier, quoted_identifier):
82
+    assert pg_quote_identifier(identifier, 'table') == quoted_identifier
83
+
84
+
85
+@pytest.mark.parametrize("identifier, id_type, msg", INVALID_QUOTES)
86
+def test_invalid_quotes(identifier, id_type, msg):
87
+    with pytest.raises(SQLParseError) as ex:
88
+        pg_quote_identifier(identifier, id_type)
89
+
90
+    ex.match(msg)
91
+
92
+
93
+@pytest.mark.parametrize("identifier, id_type, quoted_identifier, msg", HOW_MANY_DOTS)
94
+def test_how_many_dots(identifier, id_type, quoted_identifier, msg):
95
+    assert pg_quote_identifier(identifier, id_type) == quoted_identifier
96
+
97
+    with pytest.raises(SQLParseError) as ex:
98
+        pg_quote_identifier('%s.more' % identifier, id_type)
33 99
 
34
-# Note: Using nose's generator test cases here so we can't inherit from
35
-# unittest.TestCase
36
-class TestQuotePgIdentifier(object):
37
-
38
-    # These are all valid strings
39
-    # The results are based on interpreting the identifier as a table name
40
-    valid = {
41
-        # User quoted
42
-        '"public.table"': '"public.table"',
43
-        '"public"."table"': '"public"."table"',
44
-        '"schema test"."table test"': '"schema test"."table test"',
45
-
46
-        # We quote part
47
-        'public.table': '"public"."table"',
48
-        '"public".table': '"public"."table"',
49
-        'public."table"': '"public"."table"',
50
-        'schema test.table test': '"schema test"."table test"',
51
-        '"schema test".table test': '"schema test"."table test"',
52
-        'schema test."table test"': '"schema test"."table test"',
53
-
54
-        # Embedded double quotes
55
-        'table "test"': '"table ""test"""',
56
-        'public."table ""test"""': '"public"."table ""test"""',
57
-        'public.table "test"': '"public"."table ""test"""',
58
-        'schema "test".table': '"schema ""test"""."table"',
59
-        '"schema ""test""".table': '"schema ""test"""."table"',
60
-        '"""wat"""."""test"""': '"""wat"""."""test"""',
61
-        # Sigh, handle these as well:
62
-        '"no end quote': '"""no end quote"',
63
-        'schema."table': '"schema"."""table"',
64
-        '"schema.table': '"""schema"."table"',
65
-        'schema."table.something': '"schema"."""table"."something"',
66
-
67
-        # Embedded dots
68
-        '"schema.test"."table.test"': '"schema.test"."table.test"',
69
-        '"schema.".table': '"schema."."table"',
70
-        '"schema."."table"': '"schema."."table"',
71
-        'schema.".table"': '"schema".".table"',
72
-        '"schema".".table"': '"schema".".table"',
73
-        '"schema.".".table"': '"schema.".".table"',
74
-        # These are valid but maybe not what the user intended
75
-        '."table"': '".""table"""',
76
-        'table.': '"table."',
77
-    }
78
-
79
-    invalid = {
80
-        ('test.too.many.dots', 'table'): 'PostgreSQL does not support table with more than 3 dots',
81
-        ('"test.too".many.dots', 'database'): 'PostgreSQL does not support database with more than 1 dots',
82
-        ('test.too."many.dots"', 'database'): 'PostgreSQL does not support database with more than 1 dots',
83
-        ('"test"."too"."many"."dots"', 'database'): "PostgreSQL does not support database with more than 1 dots",
84
-        ('"test"."too"."many"."dots"', 'schema'): "PostgreSQL does not support schema with more than 2 dots",
85
-        ('"test"."too"."many"."dots"', 'table'): "PostgreSQL does not support table with more than 3 dots",
86
-        ('"test"."too"."many"."dots"."for"."column"', 'column'): "PostgreSQL does not support column with more than 4 dots",
87
-        ('"table "invalid" double quote"', 'table'): 'User escaped identifiers must escape extra quotes',
88
-        ('"schema "invalid"""."table "invalid"', 'table'): 'User escaped identifiers must escape extra quotes',
89
-        ('"schema."table"','table'): 'User escaped identifiers must escape extra quotes',
90
-        ('"schema".', 'table'): 'Identifier name unspecified or unquoted trailing dot',
91
-    }
92
-
93
-    def check_valid_quotes(self, identifier, quoted_identifier):
94
-        eq_(pg_quote_identifier(identifier, 'table'), quoted_identifier)
95
-
96
-    def test_valid_quotes(self):
97
-        for identifier in self.valid:
98
-            yield self.check_valid_quotes, identifier, self.valid[identifier]
99
-
100
-    def check_invalid_quotes(self, identifier, id_type, msg):
101
-        assert_raises_regexp(SQLParseError, msg, pg_quote_identifier, *(identifier, id_type))
102
-
103
-    def test_invalid_quotes(self):
104
-        for test in self.invalid:
105
-            yield self.check_invalid_quotes, test[0], test[1], self.invalid[test]
106
-
107
-    def test_how_many_dots(self):
108
-        eq_(pg_quote_identifier('role', 'role'), '"role"')
109
-        assert_raises_regexp(SQLParseError, "PostgreSQL does not support role with more than 1 dots", pg_quote_identifier, *('role.more', 'role'))
110
-
111
-        eq_(pg_quote_identifier('db', 'database'), '"db"')
112
-        assert_raises_regexp(SQLParseError, "PostgreSQL does not support database with more than 1 dots", pg_quote_identifier, *('db.more', 'database'))
113
-
114
-        eq_(pg_quote_identifier('db.schema', 'schema'), '"db"."schema"')
115
-        assert_raises_regexp(SQLParseError, "PostgreSQL does not support schema with more than 2 dots", pg_quote_identifier, *('db.schema.more', 'schema'))
116
-
117
-        eq_(pg_quote_identifier('db.schema.table', 'table'), '"db"."schema"."table"')
118
-        assert_raises_regexp(SQLParseError, "PostgreSQL does not support table with more than 3 dots", pg_quote_identifier, *('db.schema.table.more', 'table'))
119
-
120
-        eq_(pg_quote_identifier('db.schema.table.column', 'column'), '"db"."schema"."table"."column"')
121
-        assert_raises_regexp(SQLParseError, "PostgreSQL does not support column with more than 4 dots", pg_quote_identifier, *('db.schema.table.column.more', 'column'))
100
+    ex.match(msg)
... ...
@@ -20,96 +20,88 @@
20 20
 from __future__ import (absolute_import, division, print_function)
21 21
 __metaclass__ = type
22 22
 
23
-from nose import tools
24
-from ansible.compat.tests import unittest
25
-
26 23
 from ansible.parsing.splitter import split_args, parse_kv
27 24
 
25
+import pytest
26
+
27
+SPLIT_DATA = (
28
+    (u'a',
29
+        [u'a'],
30
+        {u'_raw_params': u'a'}),
31
+    (u'a=b',
32
+        [u'a=b'],
33
+        {u'a': u'b'}),
34
+    (u'a="foo bar"',
35
+        [u'a="foo bar"'],
36
+        {u'a': u'foo bar'}),
37
+    (u'"foo bar baz"',
38
+        [u'"foo bar baz"'],
39
+        {u'_raw_params': '"foo bar baz"'}),
40
+    (u'foo bar baz',
41
+        [u'foo', u'bar', u'baz'],
42
+        {u'_raw_params': u'foo bar baz'}),
43
+    (u'a=b c="foo bar"',
44
+        [u'a=b', u'c="foo bar"'],
45
+        {u'a': u'b', u'c': u'foo bar'}),
46
+    (u'a="echo \\"hello world\\"" b=bar',
47
+        [u'a="echo \\"hello world\\""', u'b=bar'],
48
+        {u'a': u'echo "hello world"', u'b': u'bar'}),
49
+    (u'a="multi\nline"',
50
+        [u'a="multi\nline"'],
51
+        {u'a': u'multi\nline'}),
52
+    (u'a="blank\n\nline"',
53
+        [u'a="blank\n\nline"'],
54
+        {u'a': u'blank\n\nline'}),
55
+    (u'a="blank\n\n\nlines"',
56
+        [u'a="blank\n\n\nlines"'],
57
+        {u'a': u'blank\n\n\nlines'}),
58
+    (u'a="a long\nmessage\\\nabout a thing\n"',
59
+        [u'a="a long\nmessage\\\nabout a thing\n"'],
60
+        {u'a': u'a long\nmessage\\\nabout a thing\n'}),
61
+    (u'a="multiline\nmessage1\\\n" b="multiline\nmessage2\\\n"',
62
+        [u'a="multiline\nmessage1\\\n"', u'b="multiline\nmessage2\\\n"'],
63
+        {u'a': 'multiline\nmessage1\\\n', u'b': u'multiline\nmessage2\\\n'}),
64
+    (u'a={{jinja}}',
65
+        [u'a={{jinja}}'],
66
+        {u'a': u'{{jinja}}'}),
67
+    (u'a={{ jinja }}',
68
+        [u'a={{ jinja }}'],
69
+        {u'a': u'{{ jinja }}'}),
70
+    (u'a="{{jinja}}"',
71
+        [u'a="{{jinja}}"'],
72
+        {u'a': u'{{jinja}}'}),
73
+    (u'a={{ jinja }}{{jinja2}}',
74
+        [u'a={{ jinja }}{{jinja2}}'],
75
+        {u'a': u'{{ jinja }}{{jinja2}}'}),
76
+    (u'a="{{ jinja }}{{jinja2}}"',
77
+        [u'a="{{ jinja }}{{jinja2}}"'],
78
+        {u'a': u'{{ jinja }}{{jinja2}}'}),
79
+    (u'a={{jinja}} b={{jinja2}}',
80
+        [u'a={{jinja}}', u'b={{jinja2}}'],
81
+        {u'a': u'{{jinja}}', u'b': u'{{jinja2}}'}),
82
+    (u'a="{{jinja}}\n" b="{{jinja2}}\n"',
83
+        [u'a="{{jinja}}\n"', u'b="{{jinja2}}\n"'],
84
+        {u'a': u'{{jinja}}\n', u'b': u'{{jinja2}}\n'}),
85
+    (u'a="café eñyei"',
86
+        [u'a="café eñyei"'],
87
+        {u'a': u'café eñyei'}),
88
+    (u'a=café b=eñyei',
89
+        [u'a=café', u'b=eñyei'],
90
+        {u'a': u'café', u'b': u'eñyei'}),
91
+    (u'a={{ foo | some_filter(\' \', " ") }} b=bar',
92
+        [u'a={{ foo | some_filter(\' \', " ") }}', u'b=bar'],
93
+        {u'a': u'{{ foo | some_filter(\' \', " ") }}', u'b': u'bar'}),
94
+)
28 95
 
29
-# Tests using nose's test generators cannot use unittest base class.
30
-# http://nose.readthedocs.org/en/latest/writing_tests.html#test-generators
31
-class TestSplitter_Gen:
32
-    SPLIT_DATA = (
33
-            (u'a',
34
-                [u'a'],
35
-                {u'_raw_params': u'a'}),
36
-            (u'a=b',
37
-                [u'a=b'],
38
-                {u'a': u'b'}),
39
-            (u'a="foo bar"',
40
-                [u'a="foo bar"'],
41
-                {u'a': u'foo bar'}),
42
-            (u'"foo bar baz"',
43
-                [u'"foo bar baz"'],
44
-                {u'_raw_params': '"foo bar baz"'}),
45
-            (u'foo bar baz',
46
-                [u'foo', u'bar', u'baz'],
47
-                {u'_raw_params': u'foo bar baz'}),
48
-            (u'a=b c="foo bar"',
49
-                [u'a=b', u'c="foo bar"'],
50
-                {u'a': u'b', u'c': u'foo bar'}),
51
-            (u'a="echo \\"hello world\\"" b=bar',
52
-                [u'a="echo \\"hello world\\""', u'b=bar'],
53
-                {u'a': u'echo "hello world"', u'b': u'bar'}),
54
-            (u'a="multi\nline"',
55
-                [u'a="multi\nline"'],
56
-                {u'a': u'multi\nline'}),
57
-            (u'a="blank\n\nline"',
58
-                [u'a="blank\n\nline"'],
59
-                {u'a': u'blank\n\nline'}),
60
-            (u'a="blank\n\n\nlines"',
61
-                [u'a="blank\n\n\nlines"'],
62
-                {u'a': u'blank\n\n\nlines'}),
63
-            (u'a="a long\nmessage\\\nabout a thing\n"',
64
-                [u'a="a long\nmessage\\\nabout a thing\n"'],
65
-                {u'a': u'a long\nmessage\\\nabout a thing\n'}),
66
-            (u'a="multiline\nmessage1\\\n" b="multiline\nmessage2\\\n"',
67
-                [u'a="multiline\nmessage1\\\n"', u'b="multiline\nmessage2\\\n"'],
68
-                {u'a': 'multiline\nmessage1\\\n', u'b': u'multiline\nmessage2\\\n'}),
69
-            (u'a={{jinja}}',
70
-                [u'a={{jinja}}'],
71
-                {u'a': u'{{jinja}}'}),
72
-            (u'a={{ jinja }}',
73
-                [u'a={{ jinja }}'],
74
-                {u'a': u'{{ jinja }}'}),
75
-            (u'a="{{jinja}}"',
76
-                [u'a="{{jinja}}"'],
77
-                {u'a': u'{{jinja}}'}),
78
-            (u'a={{ jinja }}{{jinja2}}',
79
-                [u'a={{ jinja }}{{jinja2}}'],
80
-                {u'a': u'{{ jinja }}{{jinja2}}'}),
81
-            (u'a="{{ jinja }}{{jinja2}}"',
82
-                [u'a="{{ jinja }}{{jinja2}}"'],
83
-                {u'a': u'{{ jinja }}{{jinja2}}'}),
84
-            (u'a={{jinja}} b={{jinja2}}',
85
-                [u'a={{jinja}}', u'b={{jinja2}}'],
86
-                {u'a': u'{{jinja}}', u'b': u'{{jinja2}}'}),
87
-            (u'a="{{jinja}}\n" b="{{jinja2}}\n"',
88
-                [u'a="{{jinja}}\n"', u'b="{{jinja2}}\n"'],
89
-                {u'a': u'{{jinja}}\n', u'b': u'{{jinja2}}\n'}),
90
-            (u'a="café eñyei"',
91
-                [u'a="café eñyei"'],
92
-                {u'a': u'café eñyei'}),
93
-            (u'a=café b=eñyei',
94
-                [u'a=café', u'b=eñyei'],
95
-                {u'a': u'café', u'b': u'eñyei'}),
96
-            (u'a={{ foo | some_filter(\' \', " ") }} b=bar',
97
-                [u'a={{ foo | some_filter(\' \', " ") }}', u'b=bar'],
98
-                {u'a': u'{{ foo | some_filter(\' \', " ") }}', u'b': u'bar'}),
99
-            )
96
+SPLIT_ARGS = ((test[0], test[1]) for test in SPLIT_DATA)
97
+PARSE_KV = ((test[0], test[2]) for test in SPLIT_DATA)
100 98
 
101
-    def check_split_args(self, args, expected):
102
-        tools.eq_(split_args(args), expected)
103 99
 
104
-    def test_split_args(self):
105
-        for datapoint in self.SPLIT_DATA:
106
-            yield self.check_split_args, datapoint[0], datapoint[1]
100
+@pytest.mark.parametrize("args, expected", SPLIT_ARGS)
101
+def test_split_args(args, expected):
102
+    assert split_args(args) == expected
107 103
 
108
-    def check_parse_kv(self, args, expected):
109
-        tools.eq_(parse_kv(args), expected)
110 104
 
111
-    def test_parse_kv(self):
112
-        for datapoint in self.SPLIT_DATA:
113
-            try:
114
-                yield self.check_parse_kv, datapoint[0], datapoint[2]
115
-            except: pass
105
+@pytest.mark.parametrize("args, expected", PARSE_KV)
106
+def test_parse_kv(args, expected):
107
+    assert parse_kv(args) == expected
... ...
@@ -20,39 +20,32 @@
20 20
 from __future__ import (absolute_import, division, print_function)
21 21
 __metaclass__ = type
22 22
 
23
-from nose import tools
24
-from ansible.compat.tests import unittest
25
-
26 23
 from ansible.parsing.quoting import unquote
27 24
 
25
+import pytest
28 26
 
29
-# Tests using nose's test generators cannot use unittest base class.
30
-# http://nose.readthedocs.org/en/latest/writing_tests.html#test-generators
31
-class TestUnquote:
32
-    UNQUOTE_DATA = (
33
-            (u'1', u'1'),
34
-            (u'\'1\'', u'1'),
35
-            (u'"1"', u'1'),
36
-            (u'"1 \'2\'"', u'1 \'2\''),
37
-            (u'\'1 "2"\'', u'1 "2"'),
38
-            (u'\'1 \'2\'\'', u'1 \'2\''),
39
-            (u'"1\\"', u'"1\\"'),
40
-            (u'\'1\\\'', u'\'1\\\''),
41
-            (u'"1 \\"2\\" 3"', u'1 \\"2\\" 3'),
42
-            (u'\'1 \\\'2\\\' 3\'', u'1 \\\'2\\\' 3'),
43
-            (u'"', u'"'),
44
-            (u'\'', u'\''),
45
-            # Not entirely sure these are good but they match the current
46
-            # behaviour
47
-            (u'"1""2"', u'1""2'),
48
-            (u'\'1\'\'2\'', u'1\'\'2'),
49
-            (u'"1" 2 "3"', u'1" 2 "3'),
50
-            (u'"1"\'2\'"3"', u'1"\'2\'"3'),
51
-            )
27
+UNQUOTE_DATA = (
28
+    (u'1', u'1'),
29
+    (u'\'1\'', u'1'),
30
+    (u'"1"', u'1'),
31
+    (u'"1 \'2\'"', u'1 \'2\''),
32
+    (u'\'1 "2"\'', u'1 "2"'),
33
+    (u'\'1 \'2\'\'', u'1 \'2\''),
34
+    (u'"1\\"', u'"1\\"'),
35
+    (u'\'1\\\'', u'\'1\\\''),
36
+    (u'"1 \\"2\\" 3"', u'1 \\"2\\" 3'),
37
+    (u'\'1 \\\'2\\\' 3\'', u'1 \\\'2\\\' 3'),
38
+    (u'"', u'"'),
39
+    (u'\'', u'\''),
40
+    # Not entirely sure these are good but they match the current
41
+    # behaviour
42
+    (u'"1""2"', u'1""2'),
43
+    (u'\'1\'\'2\'', u'1\'\'2'),
44
+    (u'"1" 2 "3"', u'1" 2 "3'),
45
+    (u'"1"\'2\'"3"', u'1"\'2\'"3'),
46
+)
52 47
 
53
-    def check_unquote(self, quoted, expected):
54
-        tools.eq_(unquote(quoted), expected)
55 48
 
56
-    def test_unquote(self):
57
-        for datapoint in self.UNQUOTE_DATA:
58
-            yield self.check_unquote, datapoint[0], datapoint[1]
49
+@pytest.mark.parametrize("quoted, expected", UNQUOTE_DATA)
50
+def test_unquote(quoted, expected):
51
+    assert unquote(quoted) == expected
59 52
deleted file mode 100644
... ...
@@ -1 +0,0 @@
1
-jmespath
2 1
deleted file mode 100755
... ...
@@ -1,140 +0,0 @@
1
-#!/bin/bash -eux
2
-
3
-source_root=$(python -c "from os import path; print(path.abspath(path.join(path.dirname('$0'), '../../..')))")
4
-
5
-test_image="${IMAGE:-ansible/ansible:centos7}"
6
-test_privileged="${PRIVILEGED:-false}"
7
-test_flags="${TEST_FLAGS:-}"
8
-test_target="${TARGET:-all}"
9
-test_ansible_dir="${TEST_ANSIBLE_DIR:-/root/ansible}"
10
-test_python3="${PYTHON3:-}"
11
-
12
-http_image="${HTTP_IMAGE:-ansible/ansible:httptester}"
13
-
14
-# Keep the docker containers after tests complete.
15
-# The default behavior is to always remove the containers.
16
-# Set to "onfailure" to keep the containers only on test failure.
17
-# Any other non-empty value will always keep the containers.
18
-keep_containers="${KEEP_CONTAINERS:-}"
19
-
20
-# Run the tests directly from the source directory shared with the container.
21
-# The default behavior is to run the tests on a copy of the source.
22
-# Copying the source isolates changes to the source between host and container.
23
-# Set to any non-empty value to share the source.
24
-share_source="${SHARE_SOURCE:-}"
25
-
26
-# Force ansible color output by default.
27
-# To disable color force mode use FORCE_COLOR=0
28
-force_color="${FORCE_COLOR:-1}"
29
-
30
-if [ "${SHIPPABLE_BUILD_DIR:-}" ]; then
31
-    host_shared_dir="/home/shippable/cache/build-${BUILD_NUMBER}"
32
-    controller_shared_dir="/home/shippable/cache/build-${BUILD_NUMBER}"
33
-    share_source=1
34
-    test_privileged=false # temporarily disabled to troubleshoot performance issues
35
-else
36
-    host_shared_dir="${source_root}"
37
-    controller_shared_dir=""
38
-fi
39
-
40
-if [ -z "${share_source}" ]; then
41
-    test_shared_dir="/shared"
42
-else
43
-    test_shared_dir="${test_ansible_dir}"
44
-fi
45
-
46
-container_id=
47
-httptester_id=
48
-tests_completed=
49
-
50
-function show_environment
51
-{
52
-    docker ps
53
-
54
-    if [ -d /home/shippable/cache ]; then
55
-        ls -l /home/shippable/cache
56
-    fi
57
-}
58
-
59
-function cleanup
60
-{
61
-    if [ "${controller_shared_dir}" ]; then
62
-        cp -av "${controller_shared_dir}/shippable" "${SHIPPABLE_BUILD_DIR}"
63
-        rm -rf "${controller_shared_dir}"
64
-    fi
65
-
66
-    if [ "${keep_containers}" == "onfailure" ] && [ "${tests_completed}" != "" ]; then
67
-        keep_containers=
68
-    fi
69
-
70
-    if [ "${keep_containers}" == "" ]; then
71
-        if [ "${container_id}" ]; then
72
-            docker rm -f "${container_id}"
73
-        fi
74
-
75
-        if [ "${httptester_id}" ]; then
76
-            docker rm -f "${httptester_id}"
77
-        fi
78
-    fi
79
-
80
-    show_environment
81
-}
82
-
83
-trap cleanup EXIT INT TERM
84
-docker images ansible/ansible
85
-show_environment
86
-
87
-if [ "${controller_shared_dir}" ]; then
88
-    cp -a "${SHIPPABLE_BUILD_DIR}" "${controller_shared_dir}"
89
-fi
90
-
91
-httptester_id=$(docker run -d "${http_image}")
92
-container_id=$(docker run -d \
93
-    --env "ANSIBLE_FORCE_COLOR=${force_color}" \
94
-    -v "/sys/fs/cgroup:/sys/fs/cgroup:ro" \
95
-    -v "${host_shared_dir}:${test_shared_dir}" \
96
-    --link="${httptester_id}:ansible.http.tests" \
97
-    --link="${httptester_id}:sni1.ansible.http.tests" \
98
-    --link="${httptester_id}:sni2.ansible.http.tests" \
99
-    --link="${httptester_id}:fail.ansible.http.tests" \
100
-    --privileged="${test_privileged}" \
101
-    "${test_image}")
102
-
103
-show_environment
104
-
105
-skip=
106
-
107
-if [ "${test_python3}" ]; then
108
-    docker exec "${container_id}" ln -s /usr/bin/python3 /usr/bin/python
109
-    docker exec "${container_id}" ln -s /usr/bin/pip3 /usr/bin/pip
110
-
111
-    skip+=",$(tr '\n' ',' < "${source_root}/test/utils/shippable/python3-test-tag-blacklist.txt")"
112
-fi
113
-
114
-if [ "${test_privileged}" = 'false' ]; then
115
-    skip+=",needs_privileged"
116
-fi
117
-
118
-if [ "${skip}" ]; then
119
-    test_flags="--skip-tags ${skip} ${test_flags}"
120
-fi
121
-
122
-if [ -z "${share_source}" ]; then
123
-    docker exec "${container_id}" cp -a "${test_shared_dir}" "${test_ansible_dir}"
124
-fi
125
-
126
-docker exec "${container_id}" \
127
-    pip install -r "${test_ansible_dir}/test/utils/shippable/integration-requirements.txt" --upgrade
128
-
129
-if [ "${test_python3}" ]; then
130
-    docker exec "${container_id}" sed -i -f \
131
-        "${test_ansible_dir}/test/utils/shippable/python3-test-target-blacklist.txt" \
132
-        "${test_ansible_dir}/test/integration/Makefile"
133
-fi
134
-
135
-docker exec "${container_id}" mkdir -p "${test_shared_dir}/shippable/testresults"
136
-docker exec "${container_id}" /bin/sh -c "cd '${test_ansible_dir}' && . hacking/env-setup && cd test/integration && \
137
-    JUNIT_OUTPUT_DIR='${test_shared_dir}/shippable/testresults' ANSIBLE_CALLBACK_WHITELIST=junit \
138
-    HTTPTESTER=1 TEST_FLAGS='${test_flags}' LC_ALL=en_US.utf-8 make ${test_target}"
139
-
140
-tests_completed=1
141 1
deleted file mode 100644
... ...
@@ -1,2 +0,0 @@
1
-test_hg
2
-test_service
3 1
deleted file mode 100644
... ...
@@ -13,3 +13,4 @@ python3-memcached
13 13
 python-systemd
14 14
 botocore
15 15
 boto3
16
+pytest
... ...
@@ -14,3 +14,4 @@ python-systemd
14 14
 pycrypto
15 15
 botocore
16 16
 boto3
17
+pytest