]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Pytest migration initial commit
authorKartheek Lenkala <lkarthee@gmail.com>
Sun, 22 Mar 2015 09:58:54 +0000 (15:28 +0530)
committerKartheek Lenkala <lkarthee@gmail.com>
Sun, 22 Mar 2015 09:58:54 +0000 (15:28 +0530)
22 files changed:
jinja2/testsuite/__init__.py [deleted file]
jinja2/testsuite/bytecode_cache.py [deleted file]
jinja2/testsuite/conftest.py [new file with mode: 0644]
jinja2/testsuite/doctests.py [deleted file]
jinja2/testsuite/fixtures.py [new file with mode: 0644]
jinja2/testsuite/test_api.py [moved from jinja2/testsuite/api.py with 61% similarity]
jinja2/testsuite/test_bytecode_cache.py [new file with mode: 0644]
jinja2/testsuite/test_core_tags.py [moved from jinja2/testsuite/core_tags.py with 68% similarity]
jinja2/testsuite/test_debug.py [moved from jinja2/testsuite/debug.py with 56% similarity]
jinja2/testsuite/test_ext.py [moved from jinja2/testsuite/ext.py with 88% similarity]
jinja2/testsuite/test_filters.py [moved from jinja2/testsuite/filters.py with 76% similarity]
jinja2/testsuite/test_imports.py [moved from jinja2/testsuite/imports.py with 73% similarity]
jinja2/testsuite/test_inheritance.py [moved from jinja2/testsuite/inheritance.py with 81% similarity]
jinja2/testsuite/test_lexnparse.py [moved from jinja2/testsuite/lexnparse.py with 69% similarity]
jinja2/testsuite/test_loader.py [moved from jinja2/testsuite/loader.py with 69% similarity]
jinja2/testsuite/test_regression.py [moved from jinja2/testsuite/regression.py with 74% similarity]
jinja2/testsuite/test_security.py [moved from jinja2/testsuite/security.py with 72% similarity]
jinja2/testsuite/test_tests.py [moved from jinja2/testsuite/tests.py with 80% similarity]
jinja2/testsuite/test_utils.py [moved from jinja2/testsuite/utils.py with 61% similarity]
pytest.ini [new file with mode: 0644]
setup.py
tox.ini

diff --git a/jinja2/testsuite/__init__.py b/jinja2/testsuite/__init__.py
deleted file mode 100644 (file)
index 635c83e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite
-    ~~~~~~~~~~~~~~~~
-
-    All the unittests of Jinja2.  These tests can be executed by
-    either running run-tests.py using multiple Python versions at
-    the same time.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-import re
-import sys
-import unittest
-from traceback import format_exception
-from jinja2 import loaders
-from jinja2._compat import PY2
-
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-dict_loader = loaders.DictLoader({
-    'justdict.html':        'FOO'
-})
-package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates')
-filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
-function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
-choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
-prefix_loader = loaders.PrefixLoader({
-    'a':        filesystem_loader,
-    'b':        dict_loader
-})
-
-
-class JinjaTestCase(unittest.TestCase):
-
-    ### use only these methods for testing.  If you need standard
-    ### unittest method, wrap them!
-
-    def setup(self):
-        pass
-
-    def teardown(self):
-        pass
-
-    def setUp(self):
-        self.setup()
-
-    def tearDown(self):
-        self.teardown()
-
-    def assert_equal(self, a, b):
-        return self.assertEqual(a, b)
-
-    def assert_raises(self, *args, **kwargs):
-        return self.assertRaises(*args, **kwargs)
-
-    def assert_traceback_matches(self, callback, expected_tb):
-        try:
-            callback()
-        except Exception as e:
-            tb = format_exception(*sys.exc_info())
-            if re.search(expected_tb.strip(), ''.join(tb)) is None:
-                raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
-                    % (''.join(tb), expected_tb))
-        else:
-            self.fail('Expected exception')
-
-
-def find_all_tests(suite):
-    """Yields all the tests and their names from a given suite."""
-    suites = [suite]
-    while suites:
-        s = suites.pop()
-        try:
-            suites.extend(s)
-        except TypeError:
-            yield s, '%s.%s.%s' % (
-                s.__class__.__module__,
-                s.__class__.__name__,
-                s._testMethodName
-            )
-
-
-class BetterLoader(unittest.TestLoader):
-    """A nicer loader that solves two problems.  First of all we are setting
-    up tests from different sources and we're doing this programmatically
-    which breaks the default loading logic so this is required anyways.
-    Secondly this loader has a nicer interpolation for test names than the
-    default one so you can just do ``run-tests.py ViewTestCase`` and it
-    will work.
-    """
-
-    def getRootSuite(self):
-        return suite()
-
-    def loadTestsFromName(self, name, module=None):
-        root = self.getRootSuite()
-        if name == 'suite':
-            return root
-
-        all_tests = []
-        for testcase, testname in find_all_tests(root):
-            if testname == name or \
-               testname.endswith('.' + name) or \
-               ('.' + name + '.') in testname or \
-               testname.startswith(name + '.'):
-                all_tests.append(testcase)
-
-        if not all_tests:
-            raise LookupError('could not find test case for "%s"' % name)
-
-        if len(all_tests) == 1:
-            return all_tests[0]
-        rv = unittest.TestSuite()
-        for test in all_tests:
-            rv.addTest(test)
-        return rv
-
-
-def suite():
-    from jinja2.testsuite import ext, filters, tests, core_tags, \
-         loader, inheritance, imports, lexnparse, security, api, \
-         regression, debug, utils, bytecode_cache, doctests
-    suite = unittest.TestSuite()
-    suite.addTest(ext.suite())
-    suite.addTest(filters.suite())
-    suite.addTest(tests.suite())
-    suite.addTest(core_tags.suite())
-    suite.addTest(loader.suite())
-    suite.addTest(inheritance.suite())
-    suite.addTest(imports.suite())
-    suite.addTest(lexnparse.suite())
-    suite.addTest(security.suite())
-    suite.addTest(api.suite())
-    suite.addTest(regression.suite())
-    suite.addTest(debug.suite())
-    suite.addTest(utils.suite())
-    suite.addTest(bytecode_cache.suite())
-
-    # doctests will not run on python 3 currently.  Too many issues
-    # with that, do not test that on that platform.
-    if PY2:
-        suite.addTest(doctests.suite())
-
-    return suite
-
-
-def main():
-    """Runs the testsuite as command line application."""
-    try:
-        unittest.main(testLoader=BetterLoader(), defaultTest='suite')
-    except Exception as e:
-        print('Error: %s' % e)
diff --git a/jinja2/testsuite/bytecode_cache.py b/jinja2/testsuite/bytecode_cache.py
deleted file mode 100644 (file)
index 9f5c635..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.bytecode_cache
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Test bytecode caching
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase, package_loader
-
-from jinja2 import Environment
-from jinja2.bccache import FileSystemBytecodeCache
-from jinja2.exceptions import TemplateNotFound
-
-bytecode_cache = FileSystemBytecodeCache()
-env = Environment(
-    loader=package_loader,
-    bytecode_cache=bytecode_cache,
-)
-
-
-class ByteCodeCacheTestCase(JinjaTestCase):
-
-    def test_simple(self):
-        tmpl = env.get_template('test.html')
-        assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ByteCodeCacheTestCase))
-    return suite
diff --git a/jinja2/testsuite/conftest.py b/jinja2/testsuite/conftest.py
new file mode 100644 (file)
index 0000000..f8154ea
--- /dev/null
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.conftest
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Configuration for the tests
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+from fixtures import *
diff --git a/jinja2/testsuite/doctests.py b/jinja2/testsuite/doctests.py
deleted file mode 100644 (file)
index 616d3b6..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    jinja2.testsuite.doctests
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    The doctests.  Collects all tests we want to test from
-    the Jinja modules.
-
-    :copyright: (c) 2010 by the Jinja Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import unittest
-import doctest
-
-
-def suite():
-    from jinja2 import utils, sandbox, runtime, meta, loaders, \
-        ext, environment, bccache, nodes
-    suite = unittest.TestSuite()
-    suite.addTest(doctest.DocTestSuite(utils))
-    suite.addTest(doctest.DocTestSuite(sandbox))
-    suite.addTest(doctest.DocTestSuite(runtime))
-    suite.addTest(doctest.DocTestSuite(meta))
-    suite.addTest(doctest.DocTestSuite(loaders))
-    suite.addTest(doctest.DocTestSuite(ext))
-    suite.addTest(doctest.DocTestSuite(environment))
-    suite.addTest(doctest.DocTestSuite(bccache))
-    suite.addTest(doctest.DocTestSuite(nodes))
-    return suite
diff --git a/jinja2/testsuite/fixtures.py b/jinja2/testsuite/fixtures.py
new file mode 100644 (file)
index 0000000..4b7473d
--- /dev/null
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.fixtures
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Contains fixtures used by tests.
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import pytest
+import os
+import re
+import sys
+
+from traceback import format_exception
+from jinja2 import loaders
+from jinja2._compat import PY2
+from jinja2 import Environment
+
+
+@pytest.fixture
+def env():
+    '''returns a new environment.
+    '''
+    return Environment()
+
+
+@pytest.fixture
+def dict_loader():
+    '''returns DictLoader
+    '''
+    return loaders.DictLoader({
+        'justdict.html':        'FOO'
+    })
+
+
+@pytest.fixture
+def package_loader():
+    '''returns PackageLoader initialized from templates
+    '''
+    return loaders.PackageLoader('jinja2.testsuite.res', 'templates')
+
+
+@pytest.fixture
+def filesystem_loader():
+    '''returns FileSystemLoader initialized to res/templates directory
+    '''
+    here = os.path.dirname(os.path.abspath(__file__))
+    return loaders.FileSystemLoader(here + '/res/templates')
+
+
+@pytest.fixture
+def function_loader():
+    '''returns a FunctionLoader
+    '''
+    return loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+
+
+@pytest.fixture
+def choice_loader(dict_loader, package_loader):
+    '''returns a ChoiceLoader
+    '''
+    return loaders.ChoiceLoader([dict_loader, package_loader])
+
+
+@pytest.fixture
+def prefix_loader(filesystem_loader, dict_loader):
+    '''returns a PrefixLoader
+    '''
+    return loaders.PrefixLoader({
+        'a':        filesystem_loader,
+        'b':        dict_loader
+    })
similarity index 61%
rename from jinja2/testsuite/api.py
rename to jinja2/testsuite/test_api.py
index ea3739bf4965e1ea2b8e2005199f17a08e9a4b53..37617f2ab7d4b55cf9789e8a33387c7e6ddfbbca 100644 (file)
@@ -8,24 +8,22 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
 import os
 import tempfile
 import shutil
 
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
 from jinja2 import Environment, Undefined, DebugUndefined, \
      StrictUndefined, UndefinedError, meta, \
      is_undefined, Template, DictLoader, make_logging_undefined
 from jinja2.utils import Cycler
 
-env = Environment()
-
 
-class ExtendedAPITestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.extended
+class TestExtendedAPI():
 
-    def test_item_and_attribute(self):
+    def test_item_and_attribute(self, env):
         from jinja2.sandbox import SandboxedEnvironment
 
         for env in Environment(), SandboxedEnvironment():
@@ -37,7 +35,7 @@ class ExtendedAPITestCase(JinjaTestCase):
             tmpl = env.from_string('{{ foo["items"] }}')
             assert tmpl.render(foo={'items': 42}) == '42'
 
-    def test_finalizer(self):
+    def test_finalizer(self, env):
         def finalize_none_empty(value):
             if value is None:
                 value = u''
@@ -48,7 +46,7 @@ class ExtendedAPITestCase(JinjaTestCase):
         tmpl = env.from_string('<{{ none }}>')
         assert tmpl.render() == '<>'
 
-    def test_cycler(self):
+    def test_cycler(self, env):
         items = 1, 2, 3
         c = Cycler(*items)
         for item in items + items:
@@ -59,7 +57,7 @@ class ExtendedAPITestCase(JinjaTestCase):
         c.reset()
         assert c.current == 1
 
-    def test_expressions(self):
+    def test_expressions(self, env):
         expr = env.compile_expression("foo")
         assert expr() is None
         assert expr(foo=42) == 42
@@ -69,23 +67,23 @@ class ExtendedAPITestCase(JinjaTestCase):
         expr = env.compile_expression("42 + foo")
         assert expr(foo=42) == 84
 
-    def test_template_passthrough(self):
+    def test_template_passthrough(self, env):
         t = Template('Content')
         assert env.get_template(t) is t
         assert env.select_template([t]) is t
         assert env.get_or_select_template([t]) is t
         assert env.get_or_select_template(t) is t
 
-    def test_autoescape_autoselect(self):
+    def test_autoescape_autoselect(self, env):
         def select_autoescape(name):
             if name is None or '.' not in name:
                 return False
             return name.endswith('.html')
         env = Environment(autoescape=select_autoescape,
                           loader=DictLoader({
-            'test.txt':     '{{ foo }}',
-            'test.html':    '{{ foo }}'
-        }))
+                                                'test.txt':     '{{ foo }}',
+                                                'test.html':    '{{ foo }}'
+                                            }))
         t = env.get_template('test.txt')
         assert t.render(foo='<foo>') == '<foo>'
         t = env.get_template('test.html')
@@ -94,20 +92,23 @@ class ExtendedAPITestCase(JinjaTestCase):
         assert t.render(foo='<foo>') == '<foo>'
 
 
-class MetaTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.meta
+class TestMeta():
 
-    def test_find_undeclared_variables(self):
+    def test_find_undeclared_variables(self, env):
         ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
         x = meta.find_undeclared_variables(ast)
         assert x == set(['bar'])
 
         ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
                         '{% macro meh(x) %}{{ x }}{% endmacro %}'
-                        '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
+                        '{% for item in seq %}{{ muh(item) + meh(seq) }}'
+                        '{% endfor %}')
         x = meta.find_undeclared_variables(ast)
         assert x == set(['bar', 'seq', 'muh'])
 
-    def test_find_refererenced_templates(self):
+    def test_find_refererenced_templates(self, env):
         ast = env.parse('{% extends "layout.html" %}{% include helper %}')
         i = meta.find_referenced_templates(ast)
         assert next(i) == 'layout.html'
@@ -121,7 +122,7 @@ class MetaTestCase(JinjaTestCase):
         i = meta.find_referenced_templates(ast)
         assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
 
-    def test_find_included_templates(self):
+    def test_find_included_templates(self, env):
         ast = env.parse('{% include ["foo.html", "bar.html"] %}')
         i = meta.find_referenced_templates(ast)
         assert list(i) == ['foo.html', 'bar.html']
@@ -139,28 +140,30 @@ class MetaTestCase(JinjaTestCase):
         assert list(i) == ['foo.html', 'bar.html', None]
 
 
-class StreamingTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.streaming
+class TestStreaming():
 
-    def test_basic_streaming(self):
+    def test_basic_streaming(self, env):
         tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
                                "}} - {{ item }}</li>{%- endfor %}</ul>")
         stream = tmpl.stream(seq=list(range(4)))
-        self.assert_equal(next(stream), '<ul>')
-        self.assert_equal(next(stream), '<li>1 - 0</li>')
-        self.assert_equal(next(stream), '<li>2 - 1</li>')
-        self.assert_equal(next(stream), '<li>3 - 2</li>')
-        self.assert_equal(next(stream), '<li>4 - 3</li>')
-        self.assert_equal(next(stream), '</ul>')
-
-    def test_buffered_streaming(self):
+        assert next(stream) == '<ul>'
+        assert next(stream) == '<li>1 - 0</li>'
+        assert next(stream) == '<li>2 - 1</li>'
+        assert next(stream) == '<li>3 - 2</li>'
+        assert next(stream) == '<li>4 - 3</li>'
+        assert next(stream) == '</ul>'
+
+    def test_buffered_streaming(self, env):
         tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
                                "}} - {{ item }}</li>{%- endfor %}</ul>")
         stream = tmpl.stream(seq=list(range(4)))
         stream.enable_buffering(size=3)
-        self.assert_equal(next(stream), u'<ul><li>1 - 0</li><li>2 - 1</li>')
-        self.assert_equal(next(stream), u'<li>3 - 2</li><li>4 - 3</li></ul>')
+        assert next(stream) == u'<ul><li>1 - 0</li><li>2 - 1</li>'
+        assert next(stream) == u'<li>3 - 2</li><li>4 - 3</li></ul>'
 
-    def test_streaming_behavior(self):
+    def test_streaming_behavior(self, env):
         tmpl = env.from_string("")
         stream = tmpl.stream()
         assert not stream.buffered
@@ -169,29 +172,31 @@ class StreamingTestCase(JinjaTestCase):
         stream.disable_buffering()
         assert not stream.buffered
 
-    def test_dump_stream(self):
+    def test_dump_stream(self, env):
         tmp = tempfile.mkdtemp()
         try:
             tmpl = env.from_string(u"\u2713")
             stream = tmpl.stream()
             stream.dump(os.path.join(tmp, 'dump.txt'), 'utf-8')
             with open(os.path.join(tmp, 'dump.txt'), 'rb') as f:
-                self.assertEqual(f.read(), b'\xe2\x9c\x93')
+                assert f.read() == b'\xe2\x9c\x93'
         finally:
             shutil.rmtree(tmp)
 
 
-class UndefinedTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.undefined
+class TestUndefined():
 
-    def test_stopiteration_is_undefined(self):
+    def test_stopiteration_is_undefined(self, env):
         def test():
             raise StopIteration()
         t = Template('A{{ test() }}B')
         assert t.render(test=test) == 'AB'
         t = Template('A{{ test().missingattribute }}B')
-        self.assert_raises(UndefinedError, t.render, test=test)
+        pytest.raises(UndefinedError, t.render, test=test)
 
-    def test_undefined_and_special_attributes(self):
+    def test_undefined_and_special_attributes(self, env):
         try:
             Undefined('Foo').__dict__
         except AttributeError:
@@ -199,67 +204,78 @@ class UndefinedTestCase(JinjaTestCase):
         else:
             assert False, "Expected actual attribute error"
 
-    def test_logging_undefined(self):
+    def test_logging_undefined(self, env):
         _messages = []
+
         class DebugLogger(object):
             def warning(self, msg, *args):
                 _messages.append('W:' + msg % args)
+
             def error(self, msg, *args):
                 _messages.append('E:' + msg % args)
 
         logging_undefined = make_logging_undefined(DebugLogger())
         env = Environment(undefined=logging_undefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-        self.assert_equal(_messages, [
+        assert env.from_string('{{ missing }}').render() == u''
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ missing.attribute }}').render)
+        assert env.from_string('{{ missing|list }}').render() == '[]'
+        assert env.from_string('{{ missing is not defined }}').render() \
+            == 'True'
+        assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+        assert env.from_string('{{ not missing }}').render() == 'True'
+        assert _messages == [
             'W:Template variable warning: missing is undefined',
             "E:Template variable error: 'missing' is undefined",
             'W:Template variable warning: missing is undefined',
             'W:Template variable warning: int object has no attribute missing',
             'W:Template variable warning: missing is undefined',
-        ])
+        ]
 
-    def test_default_undefined(self):
+    def test_default_undefined(self, env):
         env = Environment(undefined=Undefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), u'')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_debug_undefined(self):
+        assert env.from_string('{{ missing }}').render() == u''
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ missing.attribute }}').render)
+        assert env.from_string('{{ missing|list }}').render() == '[]'
+        assert env.from_string('{{ missing is not defined }}').render() \
+            == 'True'
+        assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+        assert env.from_string('{{ not missing }}').render() == 'True'
+
+    def test_debug_undefined(self, env):
         env = Environment(undefined=DebugUndefined)
-        self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
-        self.assert_raises(UndefinedError,
-                           env.from_string('{{ missing.attribute }}').render)
-        self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
-                          u"{{ no such element: int object['missing'] }}")
-        self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
-    def test_strict_undefined(self):
+        assert env.from_string('{{ missing }}').render() == '{{ missing }}'
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ missing.attribute }}').render)
+        assert env.from_string('{{ missing|list }}').render() == '[]'
+        assert env.from_string('{{ missing is not defined }}').render() \
+            == 'True'
+        assert env.from_string('{{ foo.missing }}').render(foo=42) \
+            == u"{{ no such element: int object['missing'] }}"
+        assert env.from_string('{{ not missing }}').render() == 'True'
+
+    def test_strict_undefined(self, env):
         env = Environment(undefined=StrictUndefined)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
-        self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
-        self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
-        self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
-        self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
-        self.assert_equal(env.from_string('{{ missing|default("default", true) }}').render(), 'default')
-
-    def test_indexing_gives_undefined(self):
+        pytest.raises(UndefinedError, env.from_string('{{ missing }}').render)
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ missing.attribute }}').render)
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ missing|list }}').render)
+        assert env.from_string('{{ missing is not defined }}').render() \
+            == 'True'
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ foo.missing }}').render, foo=42)
+        pytest.raises(UndefinedError,
+                      env.from_string('{{ not missing }}').render)
+        assert env.from_string('{{ missing|default("default", true) }}')\
+            .render() == 'default'
+
+    def test_indexing_gives_undefined(self, env):
         t = Template("{{ var[42].foo }}")
-        self.assert_raises(UndefinedError, t.render, var=0)
+        pytest.raises(UndefinedError, t.render, var=0)
 
-    def test_none_gives_proper_error(self):
+    def test_none_gives_proper_error(self, env):
         try:
             Environment().getattr(None, 'split')()
         except UndefinedError as e:
@@ -267,19 +283,10 @@ class UndefinedTestCase(JinjaTestCase):
         else:
             assert False, 'expected exception'
 
-    def test_object_repr(self):
+    def test_object_repr(self, env):
         try:
             Undefined(obj=42, name='upper')()
         except UndefinedError as e:
             assert e.message == "'int object' has no attribute 'upper'"
         else:
             assert False, 'expected exception'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
-    suite.addTest(unittest.makeSuite(MetaTestCase))
-    suite.addTest(unittest.makeSuite(StreamingTestCase))
-    suite.addTest(unittest.makeSuite(UndefinedTestCase))
-    return suite
diff --git a/jinja2/testsuite/test_bytecode_cache.py b/jinja2/testsuite/test_bytecode_cache.py
new file mode 100644 (file)
index 0000000..2ffe4c6
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2.testsuite.bytecode_cache
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test bytecode caching
+
+    :copyright: (c) 2010 by the Jinja Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import pytest
+from jinja2 import Environment
+from jinja2.bccache import FileSystemBytecodeCache
+from jinja2.exceptions import TemplateNotFound
+
+
+@pytest.fixture
+def env(package_loader):
+    bytecode_cache = FileSystemBytecodeCache()
+    return Environment(
+        loader=package_loader,
+        bytecode_cache=bytecode_cache,
+    )
+
+
+@pytest.mark.byte_code_cache
+class TestByteCodeCache():
+
+    def test_simple(self, env):
+        tmpl = env.get_template('test.html')
+        assert tmpl.render().strip() == 'BAR'
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
similarity index 68%
rename from jinja2/testsuite/core_tags.py
rename to jinja2/testsuite/test_core_tags.py
index e1cff3bfcc9554b4f273ac3bf212060648ce854f..2ea7757e4862aa8d9f96f566909cbc988692e920 100644 (file)
@@ -8,31 +8,34 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
 from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
      DictLoader
 
-env = Environment()
 
+@pytest.fixture
+def env_trim():
+    return Environment(trim_blocks=True)
 
-class ForLoopTestCase(JinjaTestCase):
 
-    def test_simple(self):
+@pytest.mark.core_tags
+@pytest.mark.for_loop
+class TestForLoop():
+
+    def test_simple(self, env):
         tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
         assert tmpl.render(seq=list(range(10))) == '0123456789'
 
-    def test_else(self):
-        tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
+    def test_else(self, env):
+        tmpl = env.from_string(
+            '{% for item in seq %}XXX{% else %}...{% endfor %}')
         assert tmpl.render() == '...'
 
-    def test_empty_blocks(self):
+    def test_empty_blocks(self, env):
         tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
         assert tmpl.render() == '<>'
 
-    def test_context_vars(self):
+    def test_context_vars(self, env):
         slist = [42, 24]
         for seq in [slist, iter(slist), reversed(slist), (_ for _ in slist)]:
             tmpl = env.from_string('''{% for item in seq -%}
@@ -53,19 +56,19 @@ class ForLoopTestCase(JinjaTestCase):
             assert one_last == 'False' and two_last == 'True'
             assert one_length == two_length == '2'
 
-    def test_cycling(self):
+    def test_cycling(self, env):
         tmpl = env.from_string('''{% for item in seq %}{{
             loop.cycle('<1>', '<2>') }}{% endfor %}{%
             for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
         output = tmpl.render(seq=list(range(4)), through=('<1>', '<2>'))
         assert output == '<1><2>' * 4
 
-    def test_scope(self):
+    def test_scope(self, env):
         tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
         output = tmpl.render(seq=list(range(10)))
         assert not output
 
-    def test_varlen(self):
+    def test_varlen(self, env):
         def inner():
             for item in range(5):
                 yield item
@@ -73,11 +76,11 @@ class ForLoopTestCase(JinjaTestCase):
         output = tmpl.render(iter=inner())
         assert output == '01234'
 
-    def test_noniter(self):
+    def test_noniter(self, env):
         tmpl = env.from_string('{% for item in none %}...{% endfor %}')
-        self.assert_raises(TypeError, tmpl.render)
+        pytest.raises(TypeError, tmpl.render)
 
-    def test_recursive(self):
+    def test_recursive(self, env):
         tmpl = env.from_string('''{% for item in seq recursive -%}
             [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
         {%- endfor %}''')
@@ -87,27 +90,27 @@ class ForLoopTestCase(JinjaTestCase):
             dict(a=3, b=[dict(a='a')])
         ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
 
-    def test_recursive_depth0(self):
+    def test_recursive_depth0(self, env):
         tmpl = env.from_string('''{% for item in seq recursive -%}
             [{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
         {%- endfor %}''')
-        self.assertEqual(tmpl.render(seq=[
+        assert tmpl.render(seq=[
             dict(a=1, b=[dict(a=1), dict(a=2)]),
             dict(a=2, b=[dict(a=1), dict(a=2)]),
             dict(a=3, b=[dict(a='a')])
-        ]), '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]')
+        ]) == '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]'
 
-    def test_recursive_depth(self):
+    def test_recursive_depth(self, env):
         tmpl = env.from_string('''{% for item in seq recursive -%}
             [{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
         {%- endfor %}''')
-        self.assertEqual(tmpl.render(seq=[
+        assert tmpl.render(seq=[
             dict(a=1, b=[dict(a=1), dict(a=2)]),
             dict(a=2, b=[dict(a=1), dict(a=2)]),
             dict(a=3, b=[dict(a='a')])
-        ]), '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]')
+        ]) == '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]'
 
-    def test_looploop(self):
+    def test_looploop(self, env):
         tmpl = env.from_string('''{% for row in table %}
             {%- set rowloop = loop -%}
             {% for cell in row -%}
@@ -116,21 +119,21 @@ class ForLoopTestCase(JinjaTestCase):
         {%- endfor %}''')
         assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
 
-    def test_reversed_bug(self):
+    def test_reversed_bug(self, env):
         tmpl = env.from_string('{% for i in items %}{{ i }}'
                                '{% if not loop.last %}'
                                ',{% endif %}{% endfor %}')
         assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
 
-    def test_loop_errors(self):
+    def test_loop_errors(self, env):
         tmpl = env.from_string('''{% for item in [1] if loop.index
                                       == 0 %}...{% endfor %}''')
-        self.assert_raises(UndefinedError, tmpl.render)
+        pytest.raises(UndefinedError, tmpl.render)
         tmpl = env.from_string('''{% for item in [] %}...{% else
             %}{{ loop }}{% endfor %}''')
         assert tmpl.render() == ''
 
-    def test_loop_filter(self):
+    def test_loop_filter(self, env):
         tmpl = env.from_string('{% for item in range(10) if item '
                                'is even %}[{{ item }}]{% endfor %}')
         assert tmpl.render() == '[0][2][4][6][8]'
@@ -139,16 +142,18 @@ class ForLoopTestCase(JinjaTestCase):
                 loop.index }}:{{ item }}]{% endfor %}''')
         assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
 
-    def test_loop_unassignable(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% for loop in seq %}...{% endfor %}')
+    def test_loop_unassignable(self, env):
+        pytest.raises(TemplateSyntaxError, env.from_string,
+                      '{% for loop in seq %}...{% endfor %}')
 
-    def test_scoped_special_var(self):
-        t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
-                            '|{{ loop.first }}{% endfor %}]{% endfor %}')
-        assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
+    def test_scoped_special_var(self, env):
+        t = env.from_string(
+            '{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+            '|{{ loop.first }}{% endfor %}]{% endfor %}')
+        assert t.render(seq=('ab', 'cd')) \
+            == '[True|True|False][False|True|False]'
 
-    def test_scoped_loop_var(self):
+    def test_scoped_loop_var(self, env):
         t = env.from_string('{% for x in seq %}{{ loop.first }}'
                             '{% for y in seq %}{% endfor %}{% endfor %}')
         assert t.render(seq='ab') == 'TrueFalse'
@@ -156,13 +161,13 @@ class ForLoopTestCase(JinjaTestCase):
                             '{{ loop.first }}{% endfor %}{% endfor %}')
         assert t.render(seq='ab') == 'TrueFalseTrueFalse'
 
-    def test_recursive_empty_loop_iter(self):
+    def test_recursive_empty_loop_iter(self, env):
         t = env.from_string('''
         {%- for item in foo recursive -%}{%- endfor -%}
         ''')
         assert t.render(dict(foo=[])) == ''
 
-    def test_call_in_loop(self):
+    def test_call_in_loop(self, env):
         t = env.from_string('''
         {%- macro do_something() -%}
             [{{ caller() }}]
@@ -176,7 +181,7 @@ class ForLoopTestCase(JinjaTestCase):
         ''')
         assert t.render() == '[1][2][3]'
 
-    def test_scoping_bug(self):
+    def test_scoping_bug(self, env):
         t = env.from_string('''
         {%- for item in foo %}...{{ item }}...{% endfor %}
         {%- macro item(a) %}...{{ a }}...{% endmacro %}
@@ -184,110 +189,119 @@ class ForLoopTestCase(JinjaTestCase):
         ''')
         assert t.render(foo=(1,)) == '...1......2...'
 
-    def test_unpacking(self):
+    def test_unpacking(self, env):
         tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
-            '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+                               '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
         assert tmpl.render() == '1|2|3'
 
 
-class IfConditionTestCase(JinjaTestCase):
+@pytest.mark.core_tags
+@pytest.mark.if_condition
+class TestIfCondition():
 
-    def test_simple(self):
+    def test_simple(self, env):
         tmpl = env.from_string('''{% if true %}...{% endif %}''')
         assert tmpl.render() == '...'
 
-    def test_elif(self):
+    def test_elif(self, env):
         tmpl = env.from_string('''{% if false %}XXX{% elif true
             %}...{% else %}XXX{% endif %}''')
         assert tmpl.render() == '...'
 
-    def test_else(self):
+    def test_else(self, env):
         tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
         assert tmpl.render() == '...'
 
-    def test_empty(self):
+    def test_empty(self, env):
         tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
         assert tmpl.render() == '[]'
 
-    def test_complete(self):
+    def test_complete(self, env):
         tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
                                'C{% else %}D{% endif %}')
         assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
 
-    def test_no_scope(self):
-        tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+    def test_no_scope(self, env):
+        tmpl = env.from_string(
+            '{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
         assert tmpl.render(a=True) == '1'
-        tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+        tmpl = env.from_string(
+            '{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
         assert tmpl.render() == '1'
 
 
-class MacrosTestCase(JinjaTestCase):
-    env = Environment(trim_blocks=True)
-
-    def test_simple(self):
-        tmpl = self.env.from_string('''\
+@pytest.mark.core_tags
+@pytest.mark.macros
+class TestMacros():
+    def test_simple(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
 {{ say_hello('Peter') }}''')
         assert tmpl.render() == 'Hello Peter!'
 
-    def test_scoping(self):
-        tmpl = self.env.from_string('''\
+    def test_scoping(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro level1(data1) %}
 {% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
 {{ level2('bar') }}{% endmacro %}
 {{ level1('foo') }}''')
         assert tmpl.render() == 'foo|bar'
 
-    def test_arguments(self):
-        tmpl = self.env.from_string('''\
+    def test_arguments(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
 {{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
         assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
 
-    def test_arguments_defaults_nonsense(self):
-        self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+    def test_arguments_defaults_nonsense(self, env_trim):
+        pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
 {% macro m(a, b=1, c) %}a={{ a }}, b={{ b }}, c={{ c }}{% endmacro %}''')
 
-    def test_caller_defaults_nonsense(self):
-        self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+    def test_caller_defaults_nonsense(self, env_trim):
+        pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
 {% macro a() %}{{ caller() }}{% endmacro %}
 {% call(x, y=1, z) a() %}{% endcall %}''')
 
-    def test_varargs(self):
-        tmpl = self.env.from_string('''\
+    def test_varargs(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
 {{ test(1, 2, 3) }}''')
         assert tmpl.render() == '1|2|3'
 
-    def test_simple_call(self):
-        tmpl = self.env.from_string('''\
+    def test_simple_call(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro test() %}[[{{ caller() }}]]{% endmacro %}\
 {% call test() %}data{% endcall %}''')
         assert tmpl.render() == '[[data]]'
 
-    def test_complex_call(self):
-        tmpl = self.env.from_string('''\
+    def test_complex_call(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
 {% call(data) test() %}{{ data }}{% endcall %}''')
         assert tmpl.render() == '[[data]]'
 
-    def test_caller_undefined(self):
-        tmpl = self.env.from_string('''\
+    def test_caller_undefined(self, env_trim):
+        tmpl = env_trim.from_string('''\
 {% set caller = 42 %}\
 {% macro test() %}{{ caller is not defined }}{% endmacro %}\
 {{ test() }}''')
         assert tmpl.render() == 'True'
 
-    def test_include(self):
-        self.env = Environment(loader=DictLoader({'include':
-            '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
-        tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
+    def test_include(self, env_trim):
+        env_trim = Environment(
+            loader=DictLoader({
+                'include': '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'
+            })
+        )
+        tmpl = env_trim.from_string(
+            '{% from "include" import test %}{{ test("foo") }}')
         assert tmpl.render() == '[foo]'
 
-    def test_macro_api(self):
-        tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
-                               '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
-                               '{% macro baz() %}{{ caller() }}{% endmacro %}')
+    def test_macro_api(self, env_trim):
+        tmpl = env_trim.from_string(
+            '{% macro foo(a, b) %}{% endmacro %}'
+            '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+            '{% macro baz() %}{{ caller() }}{% endmacro %}')
         assert tmpl.module.foo.arguments == ('a', 'b')
         assert tmpl.module.foo.defaults == ()
         assert tmpl.module.foo.name == 'foo'
@@ -301,31 +315,23 @@ class MacrosTestCase(JinjaTestCase):
         assert tmpl.module.bar.catch_varargs
         assert tmpl.module.baz.caller
 
-    def test_callself(self):
-        tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+    def test_callself(self, env_trim):
+        tmpl = env_trim.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
                                     '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
                                     '{{ foo(5) }}')
         assert tmpl.render() == '5|4|3|2|1'
 
 
-class SetTestCase(JinjaTestCase):
-    env = Environment(trim_blocks=True)
+@pytest.mark.core_tags
+@pytest.mark.set
+class TestSet():
 
-    def test_normal(self):
-        tmpl = self.env.from_string('{% set foo = 1 %}{{ foo }}')
+    def test_normal(self, env_trim):
+        tmpl = env_trim.from_string('{% set foo = 1 %}{{ foo }}')
         assert tmpl.render() == '1'
         assert tmpl.module.foo == 1
 
-    def test_block(self):
-        tmpl = self.env.from_string('{% set foo %}42{% endset %}{{ foo }}')
+    def test_block(self, env_trim):
+        tmpl = env_trim.from_string('{% set foo %}42{% endset %}{{ foo }}')
         assert tmpl.render() == '42'
         assert tmpl.module.foo == u'42'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ForLoopTestCase))
-    suite.addTest(unittest.makeSuite(IfConditionTestCase))
-    suite.addTest(unittest.makeSuite(MacrosTestCase))
-    suite.addTest(unittest.makeSuite(SetTestCase))
-    return suite
similarity index 56%
rename from jinja2/testsuite/debug.py
rename to jinja2/testsuite/test_debug.py
index 2588a83ea1845ae4c51646417dd4073ffc244801..d8617ae08e1176b964db78c6f3d0aac19cc0dac2 100644 (file)
@@ -8,41 +8,62 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
+import pytest
 
-from jinja2.testsuite import JinjaTestCase, filesystem_loader
+import re
+
+import sys
+from traceback import format_exception
 
 from jinja2 import Environment, TemplateSyntaxError
+from traceback import format_exception
+
+
+@pytest.fixture
+def fs_env(filesystem_loader):
+    '''returns a new environment.
+    '''
+    return Environment(loader=filesystem_loader)
 
-env = Environment(loader=filesystem_loader)
 
+@pytest.mark.debug
+class TestDebug():
 
-class DebugTestCase(JinjaTestCase):
+    def assert_traceback_matches(self, callback, expected_tb):
+        try:
+            callback()
+        except Exception as e:
+            tb = format_exception(*sys.exc_info())
+            if re.search(expected_tb.strip(), ''.join(tb)) is None:
+                assert False, ('Traceback did not match:\n\n%s\nexpected:\n%s' %
+                               (''.join(tb), expected_tb))
+        else:
+            assert False, 'Expected exception'
 
-    def test_runtime_error(self):
+    def test_runtime_error(self, fs_env):
         def test():
             tmpl.render(fail=lambda: 1 / 0)
-        tmpl = env.get_template('broken.html')
+        tmpl = fs_env.get_template('broken.html')
         self.assert_traceback_matches(test, r'''
   File ".*?broken.html", line 2, in (top-level template code|<module>)
     \{\{ fail\(\) \}\}
-  File ".*?debug.pyc?", line \d+, in <lambda>
+  File ".*debug?.pyc?", line \d+, in <lambda>
     tmpl\.render\(fail=lambda: 1 / 0\)
 ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
 ''')
 
-    def test_syntax_error(self):
+    def test_syntax_error(self, fs_env):
         # XXX: the .*? is necessary for python3 which does not hide
         # some of the stack frames we don't want to show.  Not sure
         # what's up with that, but that is not that critical.  Should
         # be fixed though.
-        self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
+        self.assert_traceback_matches(lambda: fs_env.get_template('syntaxerror.html'), r'''(?sm)
   File ".*?syntaxerror.html", line 4, in (template|<module>)
     \{% endif %\}.*?
 (jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
     ''')
 
-    def test_regular_syntax_error(self):
+    def test_regular_syntax_error(self, fs_env):
         def test():
             raise TemplateSyntaxError('wtf', 42)
         self.assert_traceback_matches(test, r'''
@@ -50,9 +71,3 @@ ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
     raise TemplateSyntaxError\('wtf', 42\)
 (jinja2\.exceptions\.)?TemplateSyntaxError: wtf
   line 42''')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(DebugTestCase))
-    return suite
similarity index 88%
rename from jinja2/testsuite/ext.py
rename to jinja2/testsuite/test_ext.py
index 4f0b2231fe11283aa2d91f4db124c68d29ffeb66..8985416c9cb3561fa08e2c91cf78972901530d69 100644 (file)
@@ -9,9 +9,7 @@
     :license: BSD, see LICENSE for more details.
 """
 import re
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Environment, DictLoader, contextfunction, nodes
 from jinja2.exceptions import TemplateAssertionError
@@ -100,6 +98,7 @@ newstyle_i18n_env = Environment(
 )
 newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
 
+
 class TestExtension(Extension):
     tags = set(['test'])
     ext_attr = 42
@@ -160,12 +159,14 @@ class StreamFilterExtension(Extension):
             yield Token(lineno, 'data', token.value[pos:])
 
 
-class ExtensionsTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestExtensions():
 
     def test_extend_late(self):
         env = Environment()
         env.add_extension('jinja2.ext.autoescape')
-        t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+        t = env.from_string(
+            '{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
         assert t.render() == '&lt;test&gt;'
 
     def test_loop_controls(self):
@@ -235,6 +236,7 @@ class ExtensionsTestCase(JinjaTestCase):
     def test_extension_ordering(self):
         class T1(Extension):
             priority = 1
+
         class T2(Extension):
             priority = 2
         env = Environment(extensions=[T1, T2])
@@ -243,7 +245,8 @@ class ExtensionsTestCase(JinjaTestCase):
         assert ext[1].__class__ is T2
 
 
-class InternationalizationTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestInternationalization():
 
     def test_trans(self):
         tmpl = i18n_env.get_template('child.html')
@@ -251,24 +254,28 @@ class InternationalizationTestCase(JinjaTestCase):
 
     def test_trans_plural(self):
         tmpl = i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=1) \
+            == 'Ein Benutzer online'
         assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
 
     def test_trans_plural_with_functions(self):
         tmpl = i18n_env.get_template('plural2.html')
+
         def get_user_count():
             get_user_count.called += 1
             return 1
         get_user_count.called = 0
-        assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) == '1s'
+        assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) \
+            == '1s'
         assert get_user_count.called == 1
 
     def test_complex_plural(self):
-        tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        tmpl = i18n_env.from_string(
+            '{% trans foo=42, count=2 %}{{ count }} item{% '
+            'pluralize count %}{{ count }} items{% endtrans %}')
         assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+        pytest.raises(TemplateAssertionError, i18n_env.from_string,
+                      '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
 
     def test_trans_stringformatting(self):
         tmpl = i18n_env.get_template('stringformat.html')
@@ -280,8 +287,9 @@ class InternationalizationTestCase(JinjaTestCase):
         {{ gettext('Hello World') }}
         {% trans %}Hello World{% endtrans %}
         {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('ascii')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
+        '''.encode('ascii'))  # make python 3 happy
+        assert list(babel_extract(source,
+                                  ('gettext', 'ngettext', '_'), [], {})) == [
             (2, 'gettext', u'Hello World', []),
             (3, 'gettext', u'Hello World', []),
             (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
@@ -295,15 +303,19 @@ class InternationalizationTestCase(JinjaTestCase):
         {% trans %}Hello World{% endtrans %}{# trans second #}
         {#: third #}
         {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        '''.encode('utf-8')) # make python 3 happy
-        assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
+        '''.encode('utf-8'))  # make python 3 happy
+        assert list(babel_extract(source,
+                                  ('gettext', 'ngettext', '_'),
+                                  ['trans', ':'], {})) == [
             (3, 'gettext', u'Hello World', ['first']),
             (4, 'gettext', u'Hello World', ['second']),
-            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
+            (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None),
+             ['third'])
         ]
 
 
-class NewstyleInternationalizationTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestNewstyleInternationalization():
 
     def test_trans(self):
         tmpl = newstyle_i18n_env.get_template('child.html')
@@ -311,15 +323,17 @@ class NewstyleInternationalizationTestCase(JinjaTestCase):
 
     def test_trans_plural(self):
         tmpl = newstyle_i18n_env.get_template('plural.html')
-        assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+        assert tmpl.render(LANGUAGE='de', user_count=1) \
+            == 'Ein Benutzer online'
         assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
 
     def test_complex_plural(self):
-        tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
-                                    'pluralize count %}{{ count }} items{% endtrans %}')
+        tmpl = newstyle_i18n_env.from_string(
+            '{% trans foo=42, count=2 %}{{ count }} item{% '
+            'pluralize count %}{{ count }} items{% endtrans %}')
         assert tmpl.render() == '2 items'
-        self.assert_raises(TemplateAssertionError, i18n_env.from_string,
-                           '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+        pytest.raises(TemplateAssertionError, i18n_env.from_string,
+                      '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
 
     def test_trans_stringformatting(self):
         tmpl = newstyle_i18n_env.get_template('stringformat.html')
@@ -333,8 +347,9 @@ class NewstyleInternationalizationTestCase(JinjaTestCase):
     def test_autoescape_support(self):
         env = Environment(extensions=['jinja2.ext.autoescape',
                                       'jinja2.ext.i18n'])
-        env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
-                                      lambda s, p, n: s, newstyle=True)
+        env.install_gettext_callables(
+            lambda x: u'<strong>Wert: %(name)s</strong>',
+            lambda s, p, n: s, newstyle=True)
         t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
                             '"<test>") }}{% endautoescape %}')
         assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
@@ -373,7 +388,8 @@ class NewstyleInternationalizationTestCase(JinjaTestCase):
         assert t.render() == '%(foo)s'
 
 
-class AutoEscapeTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestAutoEscape():
 
     def test_scoped_setting(self):
         env = Environment(extensions=['jinja2.ext.autoescape'],
@@ -419,8 +435,9 @@ class AutoEscapeTestCase(JinjaTestCase):
 
     def test_scoping(self):
         env = Environment(extensions=['jinja2.ext.autoescape'])
-        tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
-                               '{% endautoescape %}{{ x }}{{ "<y>" }}')
+        tmpl = env.from_string(
+            '{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+            '{% endautoescape %}{{ x }}{{ "<y>" }}')
         assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
 
     def test_volatile_scoping(self):
@@ -448,12 +465,3 @@ class AutoEscapeTestCase(JinjaTestCase):
                           autoescape=True)
         pysource = env.compile(tmplsource, raw=True)
         assert '&lt;testing&gt;\\n' in pysource
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ExtensionsTestCase))
-    suite.addTest(unittest.makeSuite(InternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
-    suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
-    return suite
similarity index 76%
rename from jinja2/testsuite/filters.py
rename to jinja2/testsuite/test_filters.py
index a32db374c498651673c0b22566df203af012623b..42c555831d70def3d4f57ad593a3be03bb6e81e5 100644 (file)
@@ -8,37 +8,34 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
 from jinja2 import Markup, Environment
 from jinja2._compat import text_type, implements_to_string
 
-env = Environment()
-
 
-class FilterTestCase(JinjaTestCase):
+@pytest.mark.filter
+class TestFilter():
 
-    def test_filter_calling(self):
+    def test_filter_calling(self, env):
         rv = env.call_filter('sum', [1, 2, 3])
-        self.assert_equal(rv, 6)
+        assert rv == 6
 
-    def test_capitalize(self):
+    def test_capitalize(self, env):
         tmpl = env.from_string('{{ "foo bar"|capitalize }}')
         assert tmpl.render() == 'Foo bar'
 
-    def test_center(self):
+    def test_center(self, env):
         tmpl = env.from_string('{{ "foo"|center(9) }}')
         assert tmpl.render() == '   foo   '
 
-    def test_default(self):
+    def test_default(self, env):
         tmpl = env.from_string(
             "{{ missing|default('no') }}|{{ false|default('no') }}|"
             "{{ false|default('no', true) }}|{{ given|default('no') }}"
         )
         assert tmpl.render(given='yes') == 'no|False|no|yes'
 
-    def test_dictsort(self):
+    def test_dictsort(self, env):
         tmpl = env.from_string(
             '{{ foo|dictsort }}|'
             '{{ foo|dictsort(true) }}|'
@@ -49,33 +46,33 @@ class FilterTestCase(JinjaTestCase):
                        "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
                        "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
 
-    def test_batch(self):
+    def test_batch(self, env):
         tmpl = env.from_string("{{ foo|batch(3)|list }}|"
                                "{{ foo|batch(3, 'X')|list }}")
         out = tmpl.render(foo=list(range(10)))
         assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
                        "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
 
-    def test_slice(self):
+    def test_slice(self, env):
         tmpl = env.from_string('{{ foo|slice(3)|list }}|'
                                '{{ foo|slice(3, "X")|list }}')
         out = tmpl.render(foo=list(range(10)))
         assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
                        "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
 
-    def test_escape(self):
+    def test_escape(self, env):
         tmpl = env.from_string('''{{ '<">&'|escape }}''')
         out = tmpl.render()
         assert out == '&lt;&#34;&gt;&amp;'
 
-    def test_striptags(self):
+    def test_striptags(self, env):
         tmpl = env.from_string('''{{ foo|striptags }}''')
         out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
                           'example</a> link</p>\n<p>to a webpage</p> '
                           '<!-- <p>and some commented stuff</p> -->')
         assert out == 'just a small example link to a webpage'
 
-    def test_filesizeformat(self):
+    def test_filesizeformat(self, env):
         tmpl = env.from_string(
             '{{ 100|filesizeformat }}|'
             '{{ 1000|filesizeformat }}|'
@@ -89,12 +86,12 @@ class FilterTestCase(JinjaTestCase):
             '{{ 1000000000000|filesizeformat(true) }}'
         )
         out = tmpl.render()
-        self.assert_equal(out, (
+        assert out == (
             '100 Bytes|1.0 kB|1.0 MB|1.0 GB|1.0 TB|100 Bytes|'
             '1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
-        ))
+        )
 
-    def test_filesizeformat_issue59(self):
+    def test_filesizeformat_issue59(self, env):
         tmpl = env.from_string(
             '{{ 300|filesizeformat }}|'
             '{{ 3000|filesizeformat }}|'
@@ -106,96 +103,96 @@ class FilterTestCase(JinjaTestCase):
             '{{ 3000000|filesizeformat(true) }}'
         )
         out = tmpl.render()
-        self.assert_equal(out, (
+        assert out == (
             '300 Bytes|3.0 kB|3.0 MB|3.0 GB|3.0 TB|300 Bytes|'
             '2.9 KiB|2.9 MiB'
-        ))
-
+        )
 
-    def test_first(self):
+    def test_first(self, env):
         tmpl = env.from_string('{{ foo|first }}')
         out = tmpl.render(foo=list(range(10)))
         assert out == '0'
 
-    def test_float(self):
+    def test_float(self, env):
         tmpl = env.from_string('{{ "42"|float }}|'
                                '{{ "ajsghasjgd"|float }}|'
                                '{{ "32.32"|float }}')
         out = tmpl.render()
         assert out == '42.0|0.0|32.32'
 
-    def test_format(self):
+    def test_format(self, env):
         tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
         out = tmpl.render()
         assert out == 'a|b'
 
-    def test_indent(self):
+    def test_indent(self, env):
         tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
         text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
         out = tmpl.render(foo=text)
         assert out == ('foo bar foo bar\n  foo bar foo bar|  '
                        'foo bar foo bar\n  foo bar foo bar')
 
-    def test_int(self):
+    def test_int(self, env):
         tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
                                '{{ "32.32"|int }}')
         out = tmpl.render()
         assert out == '42|0|32'
 
-    def test_join(self):
+    def test_join(self, env):
         tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
         out = tmpl.render()
         assert out == '1|2|3'
 
         env2 = Environment(autoescape=True)
-        tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+        tmpl = env2.from_string(
+            '{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
         assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
 
-    def test_join_attribute(self):
+    def test_join_attribute(self, env):
         class User(object):
             def __init__(self, username):
                 self.username = username
         tmpl = env.from_string('''{{ users|join(', ', 'username') }}''')
         assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar'
 
-    def test_last(self):
+    def test_last(self, env):
         tmpl = env.from_string('''{{ foo|last }}''')
         out = tmpl.render(foo=list(range(10)))
         assert out == '9'
 
-    def test_length(self):
+    def test_length(self, env):
         tmpl = env.from_string('''{{ "hello world"|length }}''')
         out = tmpl.render()
         assert out == '11'
 
-    def test_lower(self):
+    def test_lower(self, env):
         tmpl = env.from_string('''{{ "FOO"|lower }}''')
         out = tmpl.render()
         assert out == 'foo'
 
-    def test_pprint(self):
+    def test_pprint(self, env):
         from pprint import pformat
         tmpl = env.from_string('''{{ data|pprint }}''')
         data = list(range(1000))
         assert tmpl.render(data=data) == pformat(data)
 
-    def test_random(self):
+    def test_random(self, env):
         tmpl = env.from_string('''{{ seq|random }}''')
         seq = list(range(100))
         for _ in range(10):
             assert int(tmpl.render(seq=seq)) in seq
 
-    def test_reverse(self):
+    def test_reverse(self, env):
         tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
                                '{{ [1, 2, 3]|reverse|list }}')
         assert tmpl.render() == 'raboof|[3, 2, 1]'
 
-    def test_string(self):
+    def test_string(self, env):
         x = [1, 2, 3, 4, 5]
         tmpl = env.from_string('''{{ obj|string }}''')
         assert tmpl.render(obj=x) == text_type(x)
 
-    def test_title(self):
+    def test_title(self, env):
         tmpl = env.from_string('''{{ "foo bar"|title }}''')
         assert tmpl.render() == "Foo Bar"
         tmpl = env.from_string('''{{ "foo's bar"|title }}''')
@@ -219,7 +216,7 @@ class FilterTestCase(JinjaTestCase):
         out = tmpl.render(data=Foo())
         assert out == 'Foo-Bar'
 
-    def test_truncate(self):
+    def test_truncate(self, env):
         tmpl = env.from_string(
             '{{ data|truncate(15, true, ">>>") }}|'
             '{{ data|truncate(15, false, ">>>") }}|'
@@ -230,7 +227,7 @@ class FilterTestCase(JinjaTestCase):
         msg = 'Current output: %s' % out
         assert out == 'foobar baz b>>>|foobar baz >>>|foobar baz bar', msg
 
-    def test_truncate_very_short(self):
+    def test_truncate_very_short(self, env):
         tmpl = env.from_string(
             '{{ "foo bar baz"|truncate(9) }}|'
             '{{ "foo bar baz"|truncate(9, true) }}'
@@ -238,45 +235,55 @@ class FilterTestCase(JinjaTestCase):
         out = tmpl.render()
         assert out == 'foo ...|foo ba...', out
 
-    def test_truncate_end_length(self):
+    def test_truncate_end_length(self, env):
         tmpl = env.from_string('{{ "Joel is a slug"|truncate(9, true) }}')
         out = tmpl.render()
         assert out == 'Joel i...', 'Current output: %s' % out
 
-    def test_upper(self):
+    def test_upper(self, env):
         tmpl = env.from_string('{{ "foo"|upper }}')
         assert tmpl.render() == 'FOO'
 
-    def test_urlize(self):
-        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
+    def test_urlize(self, env):
+        tmpl = env.from_string(
+            '{{ "foo http://www.example.com/ bar"|urlize }}')
         assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
                                 'http://www.example.com/</a> bar'
 
-    def test_urlize_target_parameter(self):
-        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize(target="_blank") }}')
-        assert tmpl.render() == 'foo <a href="http://www.example.com/" target="_blank">'\
-                                'http://www.example.com/</a> bar'
-        tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize(target=42) }}')
+    def test_urlize_target_parameter(self, env):
+        tmpl = env.from_string(
+            '{{ "foo http://www.example.com/ bar"|urlize(target="_blank") }}'
+        )
+        assert tmpl.render() \
+            == 'foo <a href="http://www.example.com/" target="_blank">'\
+            'http://www.example.com/</a> bar'
+        tmpl = env.from_string(
+            '{{ "foo http://www.example.com/ bar"|urlize(target=42) }}'
+        )
         assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
                                 'http://www.example.com/</a> bar'
 
-    def test_wordcount(self):
+    def test_wordcount(self, env):
         tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
         assert tmpl.render() == '3'
 
-    def test_block(self):
-        tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
+    def test_block(self, env):
+        tmpl = env.from_string(
+            '{% filter lower|escape %}<HEHE>{% endfilter %}'
+        )
         assert tmpl.render() == '&lt;hehe&gt;'
 
-    def test_chaining(self):
-        tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
+    def test_chaining(self, env):
+        tmpl = env.from_string(
+            '''{{ ['<foo>', '<bar>']|first|upper|escape }}'''
+        )
         assert tmpl.render() == '&lt;FOO&gt;'
 
-    def test_sum(self):
+    def test_sum(self, env):
         tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
         assert tmpl.render() == '21'
 
-    def test_sum_attributes(self):
+    def test_sum_attributes(self, env):
         tmpl = env.from_string('''{{ values|sum('value') }}''')
         assert tmpl.render(values=[
             {'value': 23},
@@ -284,7 +291,7 @@ class FilterTestCase(JinjaTestCase):
             {'value': 18},
         ]) == '42'
 
-    def test_sum_attributes_nested(self):
+    def test_sum_attributes_nested(self, env):
         tmpl = env.from_string('''{{ values|sum('real.value') }}''')
         assert tmpl.render(values=[
             {'real': {'value': 23}},
@@ -292,7 +299,7 @@ class FilterTestCase(JinjaTestCase):
             {'real': {'value': 18}},
         ]) == '42'
 
-    def test_sum_attributes_tuple(self):
+    def test_sum_attributes_tuple(self, env):
         tmpl = env.from_string('''{{ values.items()|sum('1') }}''')
         assert tmpl.render(values={
             'foo': 23,
@@ -300,54 +307,57 @@ class FilterTestCase(JinjaTestCase):
             'baz': 18,
         }) == '42'
 
-    def test_abs(self):
+    def test_abs(self, env):
         tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
         assert tmpl.render() == '1|1', tmpl.render()
 
-    def test_round_positive(self):
+    def test_round_positive(self, env):
         tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
                                "{{ 2.1234|round(3, 'floor') }}|"
                                "{{ 2.1|round(0, 'ceil') }}")
         assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
 
-    def test_round_negative(self):
+    def test_round_negative(self, env):
         tmpl = env.from_string('{{ 21.3|round(-1)}}|'
                                "{{ 21.3|round(-1, 'ceil')}}|"
                                "{{ 21.3|round(-1, 'floor')}}")
-        assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
+        assert tmpl.render() == '20.0|30.0|20.0', tmpl.render()
 
-    def test_xmlattr(self):
-        tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
-                               "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+    def test_xmlattr(self, env):
+        tmpl = env.from_string(
+            "{{ {'foo': 42, 'bar': 23, 'fish': none, "
+            "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
         out = tmpl.render().split()
         assert len(out) == 3
         assert 'foo="42"' in out
         assert 'bar="23"' in out
         assert 'blub:blub="&lt;?&gt;"' in out
 
-    def test_sort1(self):
-        tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+    def test_sort1(self, env):
+        tmpl = env.from_string(
+            '{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
         assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
 
-    def test_sort2(self):
+    def test_sort2(self, env):
         tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort) }}')
         assert tmpl.render() == 'AbcD'
 
-    def test_sort3(self):
+    def test_sort3(self, env):
         tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
         assert tmpl.render() == "['Bar', 'blah', 'foo']"
 
-    def test_sort4(self):
+    def test_sort4(self, env):
         @implements_to_string
         class Magic(object):
             def __init__(self, value):
                 self.value = value
+
             def __str__(self):
                 return text_type(self.value)
         tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''')
         assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234'
 
-    def test_groupby(self):
+    def test_groupby(self, env):
         tmpl = env.from_string('''
         {%- for grouper, list in [{'foo': 1, 'bar': 2},
                                   {'foo': 2, 'bar': 3},
@@ -362,19 +372,20 @@ class FilterTestCase(JinjaTestCase):
             ""
         ]
 
-    def test_groupby_tuple_index(self):
+    def test_groupby_tuple_index(self, env):
         tmpl = env.from_string('''
         {%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%}
             {{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}|
         {%- endfor %}''')
         assert tmpl.render() == 'a:1:2|b:1|'
 
-    def test_groupby_multidot(self):
+    def test_groupby_multidot(self, env):
         class Date(object):
             def __init__(self, day, month, year):
                 self.day = day
                 self.month = month
                 self.year = year
+
         class Article(object):
             def __init__(self, title, *date):
                 self.date = Date(*date)
@@ -395,12 +406,12 @@ class FilterTestCase(JinjaTestCase):
             ''
         ]
 
-    def test_filtertag(self):
+    def test_filtertag(self, env):
         tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
                                "foobar{% endfilter %}")
         assert tmpl.render() == 'fooBAR'
 
-    def test_replace(self):
+    def test_replace(self, env):
         env = Environment()
         tmpl = env.from_string('{{ string|replace("o", 42) }}')
         assert tmpl.render(string='<foo>') == '<f4242>'
@@ -412,35 +423,36 @@ class FilterTestCase(JinjaTestCase):
         tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
         assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
 
-    def test_forceescape(self):
+    def test_forceescape(self, env):
         tmpl = env.from_string('{{ x|forceescape }}')
         assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
 
-    def test_safe(self):
+    def test_safe(self, env):
         env = Environment(autoescape=True)
         tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
         assert tmpl.render() == '<div>foo</div>'
         tmpl = env.from_string('{{ "<div>foo</div>" }}')
         assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
 
-    def test_urlencode(self):
+    def test_urlencode(self, env):
         env = Environment(autoescape=True)
         tmpl = env.from_string('{{ "Hello, world!"|urlencode }}')
         assert tmpl.render() == 'Hello%2C%20world%21'
         tmpl = env.from_string('{{ o|urlencode }}')
-        assert tmpl.render(o=u"Hello, world\u203d") == "Hello%2C%20world%E2%80%BD"
+        assert tmpl.render(o=u"Hello, world\u203d") \
+            == "Hello%2C%20world%E2%80%BD"
         assert tmpl.render(o=(("f", 1),)) == "f=1"
         assert tmpl.render(o=(('f', 1), ("z", 2))) == "f=1&amp;z=2"
         assert tmpl.render(o=((u"\u203d", 1),)) == "%E2%80%BD=1"
         assert tmpl.render(o={u"\u203d": 1}) == "%E2%80%BD=1"
         assert tmpl.render(o={0: 1}) == "0=1"
 
-    def test_simple_map(self):
+    def test_simple_map(self, env):
         env = Environment()
         tmpl = env.from_string('{{ ["1", "2", "3"]|map("int")|sum }}')
-        self.assertEqual(tmpl.render(), '6')
+        assert tmpl.render() == '6'
 
-    def test_attribute_map(self):
+    def test_attribute_map(self, env):
         class User(object):
             def __init__(self, name):
                 self.name = name
@@ -451,34 +463,38 @@ class FilterTestCase(JinjaTestCase):
             User('mike'),
         ]
         tmpl = env.from_string('{{ users|map(attribute="name")|join("|") }}')
-        self.assertEqual(tmpl.render(users=users), 'john|jane|mike')
+        assert tmpl.render(users=users) == 'john|jane|mike'
 
-    def test_empty_map(self):
+    def test_empty_map(self, env):
         env = Environment()
         tmpl = env.from_string('{{ none|map("upper")|list }}')
-        self.assertEqual(tmpl.render(), '[]')
+        assert tmpl.render() == '[]'
 
-    def test_simple_select(self):
+    def test_simple_select(self, env):
         env = Environment()
         tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|select("odd")|join("|") }}')
-        self.assertEqual(tmpl.render(), '1|3|5')
+        assert tmpl.render() == '1|3|5'
 
-    def test_bool_select(self):
+    def test_bool_select(self, env):
         env = Environment()
-        tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}')
-        self.assertEqual(tmpl.render(), '1|2|3|4|5')
+        tmpl = env.from_string(
+            '{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}'
+        )
+        assert tmpl.render() == '1|2|3|4|5'
 
-    def test_simple_reject(self):
+    def test_simple_reject(self, env):
         env = Environment()
         tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|reject("odd")|join("|") }}')
-        self.assertEqual(tmpl.render(), '2|4')
+        assert tmpl.render() == '2|4'
 
-    def test_bool_reject(self):
+    def test_bool_reject(self, env):
         env = Environment()
-        tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}')
-        self.assertEqual(tmpl.render(), 'None|False|0')
+        tmpl = env.from_string(
+            '{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}'
+        )
+        assert tmpl.render() == 'None|False|0'
 
-    def test_simple_select_attr(self):
+    def test_simple_select_attr(self, env):
         class User(object):
             def __init__(self, name, is_active):
                 self.name = name
@@ -489,11 +505,13 @@ class FilterTestCase(JinjaTestCase):
             User('jane', True),
             User('mike', False),
         ]
-        tmpl = env.from_string('{{ users|selectattr("is_active")|'
-            'map(attribute="name")|join("|") }}')
-        self.assertEqual(tmpl.render(users=users), 'john|jane')
+        tmpl = env.from_string(
+            '{{ users|selectattr("is_active")|'
+            'map(attribute="name")|join("|") }}'
+        )
+        assert tmpl.render(users=users) == 'john|jane'
 
-    def test_simple_reject_attr(self):
+    def test_simple_reject_attr(self, env):
         class User(object):
             def __init__(self, name, is_active):
                 self.name = name
@@ -505,10 +523,10 @@ class FilterTestCase(JinjaTestCase):
             User('mike', False),
         ]
         tmpl = env.from_string('{{ users|rejectattr("is_active")|'
-            'map(attribute="name")|join("|") }}')
-        self.assertEqual(tmpl.render(users=users), 'mike')
+                               'map(attribute="name")|join("|") }}')
+        assert tmpl.render(users=users) == 'mike'
 
-    def test_func_select_attr(self):
+    def test_func_select_attr(self, env):
         class User(object):
             def __init__(self, id, name):
                 self.id = id
@@ -520,10 +538,10 @@ class FilterTestCase(JinjaTestCase):
             User(3, 'mike'),
         ]
         tmpl = env.from_string('{{ users|selectattr("id", "odd")|'
-            'map(attribute="name")|join("|") }}')
-        self.assertEqual(tmpl.render(users=users), 'john|mike')
+                               'map(attribute="name")|join("|") }}')
+        assert tmpl.render(users=users) == 'john|mike'
 
-    def test_func_reject_attr(self):
+    def test_func_reject_attr(self, env):
         class User(object):
             def __init__(self, id, name):
                 self.id = id
@@ -535,11 +553,5 @@ class FilterTestCase(JinjaTestCase):
             User(3, 'mike'),
         ]
         tmpl = env.from_string('{{ users|rejectattr("id", "odd")|'
-            'map(attribute="name")|join("|") }}')
-        self.assertEqual(tmpl.render(users=users), 'jane')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(FilterTestCase))
-    return suite
+                               'map(attribute="name")|join("|") }}')
+        assert tmpl.render(users=users) == 'jane'
similarity index 73%
rename from jinja2/testsuite/imports.py
rename to jinja2/testsuite/test_imports.py
index 3db9008deb444ccd02fdb7aac44f0961c0e14000..643c995c6e6ade0cbdc6414f5ffa7907ca607635 100644 (file)
@@ -8,46 +8,56 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Environment, DictLoader
 from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
 
 
-test_env = Environment(loader=DictLoader(dict(
-    module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
-    header='[{{ foo }}|{{ 23 }}]',
-    o_printer='({{ o }})'
-)))
-test_env.globals['bar'] = 23
+@pytest.fixture
+def test_env():
+    env = Environment(loader=DictLoader(dict(
+        module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+        header='[{{ foo }}|{{ 23 }}]',
+        o_printer='({{ o }})'
+    )))
+    env.globals['bar'] = 23
+    return env
 
 
-class ImportsTestCase(JinjaTestCase):
+@pytest.mark.imports
+class TestImports():
 
-    def test_context_imports(self):
+    def test_context_imports(self, test_env):
         t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
         assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
+        t = test_env.from_string(
+            '{% import "module" as m without context %}{{ m.test() }}'
+        )
         assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
+        t = test_env.from_string(
+            '{% import "module" as m with context %}{{ m.test() }}'
+        )
         assert t.render(foo=42) == '[42|23]'
         t = test_env.from_string('{% from "module" import test %}{{ test() }}')
         assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
+        t = test_env.from_string(
+            '{% from "module" import test without context %}{{ test() }}'
+        )
         assert t.render(foo=42) == '[|23]'
-        t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
+        t = test_env.from_string(
+            '{% from "module" import test with context %}{{ test() }}'
+        )
         assert t.render(foo=42) == '[42|23]'
 
-    def test_trailing_comma(self):
+    def test_trailing_comma(self, test_env):
         test_env.from_string('{% from "foo" import bar, baz with context %}')
         test_env.from_string('{% from "foo" import bar, baz, with context %}')
         test_env.from_string('{% from "foo" import bar, with context %}')
         test_env.from_string('{% from "foo" import bar, with, context %}')
         test_env.from_string('{% from "foo" import bar, with with context %}')
 
-    def test_exports(self):
+    def test_exports(self, test_env):
         m = test_env.from_string('''
             {% macro toplevel() %}...{% endmacro %}
             {% macro __private() %}...{% endmacro %}
@@ -62,9 +72,11 @@ class ImportsTestCase(JinjaTestCase):
         assert not hasattr(m, 'notthere')
 
 
-class IncludesTestCase(JinjaTestCase):
+@pytest.mark.imports
+@pytest.mark.includes
+class TestIncludes():
 
-    def test_context_include(self):
+    def test_context_include(self, test_env):
         t = test_env.from_string('{% include "header" %}')
         assert t.render(foo=42) == '[42|23]'
         t = test_env.from_string('{% include "header" with context %}')
@@ -72,15 +84,17 @@ class IncludesTestCase(JinjaTestCase):
         t = test_env.from_string('{% include "header" without context %}')
         assert t.render(foo=42) == '[|23]'
 
-    def test_choice_includes(self):
+    def test_choice_includes(self, test_env):
         t = test_env.from_string('{% include ["missing", "header"] %}')
         assert t.render(foo=42) == '[42|23]'
 
-        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+        t = test_env.from_string(
+            '{% include ["missing", "missing2"] ignore missing %}'
+        )
         assert t.render(foo=42) == ''
 
         t = test_env.from_string('{% include ["missing", "missing2"] %}')
-        self.assert_raises(TemplateNotFound, t.render)
+        pytest.raises(TemplateNotFound, t.render)
         try:
             t.render()
         except TemplatesNotFound as e:
@@ -106,22 +120,22 @@ class IncludesTestCase(JinjaTestCase):
         t = test_env.from_string('{% include [x] %}')
         test_includes(t, x='header')
 
-    def test_include_ignoring_missing(self):
+    def test_include_ignoring_missing(self, test_env):
         t = test_env.from_string('{% include "missing" %}')
-        self.assert_raises(TemplateNotFound, t.render)
+        pytest.raises(TemplateNotFound, t.render)
         for extra in '', 'with context', 'without context':
             t = test_env.from_string('{% include "missing" ignore missing ' +
                                      extra + ' %}')
             assert t.render() == ''
 
-    def test_context_include_with_overrides(self):
+    def test_context_include_with_overrides(self, test_env):
         env = Environment(loader=DictLoader(dict(
             main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
             item="{{ item }}"
         )))
         assert env.get_template("main").render() == "123"
 
-    def test_unoptimized_scopes(self):
+    def test_unoptimized_scopes(self, test_env):
         t = test_env.from_string("""
             {% macro outer(o) %}
             {% macro inner() %}
@@ -132,10 +146,3 @@ class IncludesTestCase(JinjaTestCase):
             {{ outer("FOO") }}
         """)
         assert t.render().strip() == '(FOO)'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(ImportsTestCase))
-    suite.addTest(unittest.makeSuite(IncludesTestCase))
-    return suite
similarity index 81%
rename from jinja2/testsuite/inheritance.py
rename to jinja2/testsuite/test_inheritance.py
index e0f51cda9206ef9666b0004115b5c22e496fae4f..1cb7390441c09e3ca48ca86f31737489c91e139a 100644 (file)
@@ -8,9 +8,7 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Environment, DictLoader, TemplateError
 
@@ -66,45 +64,48 @@ DOUBLEEXTENDS = '''\
 '''
 
 
-env = Environment(loader=DictLoader({
-    'layout':       LAYOUTTEMPLATE,
-    'level1':       LEVEL1TEMPLATE,
-    'level2':       LEVEL2TEMPLATE,
-    'level3':       LEVEL3TEMPLATE,
-    'level4':       LEVEL4TEMPLATE,
-    'working':      WORKINGTEMPLATE,
-    'doublee':      DOUBLEEXTENDS,
-}), trim_blocks=True)
+@pytest.fixture
+def env():
+    return Environment(loader=DictLoader({
+        'layout':       LAYOUTTEMPLATE,
+        'level1':       LEVEL1TEMPLATE,
+        'level2':       LEVEL2TEMPLATE,
+        'level3':       LEVEL3TEMPLATE,
+        'level4':       LEVEL4TEMPLATE,
+        'working':      WORKINGTEMPLATE,
+        'doublee':      DOUBLEEXTENDS,
+    }), trim_blocks=True)
 
 
-class InheritanceTestCase(JinjaTestCase):
+@pytest.mark.inheritance
+class TestInheritance():
 
-    def test_layout(self):
+    def test_layout(self, env):
         tmpl = env.get_template('layout')
         assert tmpl.render() == ('|block 1 from layout|block 2 from '
                                  'layout|nested block 4 from layout|')
 
-    def test_level1(self):
+    def test_level1(self, env):
         tmpl = env.get_template('level1')
         assert tmpl.render() == ('|block 1 from level1|block 2 from '
                                  'layout|nested block 4 from layout|')
 
-    def test_level2(self):
+    def test_level2(self, env):
         tmpl = env.get_template('level2')
         assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
                                  'level2|nested block 4 from layout|')
 
-    def test_level3(self):
+    def test_level3(self, env):
         tmpl = env.get_template('level3')
         assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
                                  'block 4 from level3|')
 
-    def test_level4(sel):
+    def test_level4(self, env):
         tmpl = env.get_template('level4')
         assert tmpl.render() == ('|block 1 from level1|block 5 from '
                                  'level3|block 3 from level4|')
 
-    def test_super(self):
+    def test_super(self, env):
         env = Environment(loader=DictLoader({
             'a': '{% block intro %}INTRO{% endblock %}|'
                  'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
@@ -117,23 +118,24 @@ class InheritanceTestCase(JinjaTestCase):
         tmpl = env.get_template('c')
         assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
 
-    def test_working(self):
+    def test_working(self, env):
         tmpl = env.get_template('working')
 
-    def test_reuse_blocks(self):
+    def test_reuse_blocks(self, env):
         tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
                                '{% endblock %}|{{ self.foo() }}')
         assert tmpl.render() == '42|42|42'
 
-    def test_preserve_blocks(self):
+    def test_preserve_blocks(self, env):
         env = Environment(loader=DictLoader({
-            'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
+            'a': '{% if false %}{% block x %}A{% endblock %}'
+            '{% endif %}{{ self.x() }}',
             'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
         }))
         tmpl = env.get_template('b')
         assert tmpl.render() == 'BA'
 
-    def test_dynamic_inheritance(self):
+    def test_dynamic_inheritance(self, env):
         env = Environment(loader=DictLoader({
             'master1': 'MASTER1{% block x %}{% endblock %}',
             'master2': 'MASTER2{% block x %}{% endblock %}',
@@ -143,19 +145,20 @@ class InheritanceTestCase(JinjaTestCase):
         for m in range(1, 3):
             assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
 
-    def test_multi_inheritance(self):
+    def test_multi_inheritance(self, env):
         env = Environment(loader=DictLoader({
             'master1': 'MASTER1{% block x %}{% endblock %}',
             'master2': 'MASTER2{% block x %}{% endblock %}',
-            'child': '''{% if master %}{% extends master %}{% else %}{% extends
-                        'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+            'child':
+                '''{% if master %}{% extends master %}{% else %}{% extends
+                'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
         }))
         tmpl = env.get_template('child')
         assert tmpl.render(master='master2') == 'MASTER2CHILD'
         assert tmpl.render(master='master1') == 'MASTER1CHILD'
         assert tmpl.render() == 'MASTER1CHILD'
 
-    def test_scoped_block(self):
+    def test_scoped_block(self, env):
         env = Environment(loader=DictLoader({
             'master.html': '{% for item in seq %}[{% block item scoped %}'
                            '{% endblock %}]{% endfor %}'
@@ -164,7 +167,7 @@ class InheritanceTestCase(JinjaTestCase):
                             '{{ item }}{% endblock %}')
         assert t.render(seq=list(range(5))) == '[0][1][2][3][4]'
 
-    def test_super_in_scoped_block(self):
+    def test_super_in_scoped_block(self, env):
         env = Environment(loader=DictLoader({
             'master.html': '{% for item in seq %}[{% block item scoped %}'
                            '{{ item }}{% endblock %}]{% endfor %}'
@@ -173,7 +176,7 @@ class InheritanceTestCase(JinjaTestCase):
                             '{{ super() }}|{{ item * 2 }}{% endblock %}')
         assert t.render(seq=list(range(5))) == '[0|0][1|2][2|4][3|6][4|8]'
 
-    def test_scoped_block_after_inheritance(self):
+    def test_scoped_block_after_inheritance(self, env):
         env = Environment(loader=DictLoader({
             'layout.html': '''
             {% block useless %}{% endblock %}
@@ -197,9 +200,10 @@ class InheritanceTestCase(JinjaTestCase):
         assert rv == ['43', '44', '45']
 
 
-class BugFixTestCase(JinjaTestCase):
+@pytest.mark.inheritance
+class TestBugFix():
 
-    def test_fixed_macro_scoping_bug(self):
+    def test_fixed_macro_scoping_bug(self, env):
         assert Environment(loader=DictLoader({
             'test.html': '''\
         {% extends 'details.html' %}
@@ -231,9 +235,10 @@ class BugFixTestCase(JinjaTestCase):
             'standard.html': '''
         {% block content %}&nbsp;{% endblock %}
         '''
-        })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
+        })).get_template("test.html").render().split() \
+            == [u'outer_box', u'my_macro']
 
-    def test_double_extends(self):
+    def test_double_extends(self, env):
         """Ensures that a template with more than 1 {% extends ... %} usage
         raises a ``TemplateError``.
         """
@@ -241,10 +246,3 @@ class BugFixTestCase(JinjaTestCase):
             tmpl = env.get_template('doublee')
         except Exception as e:
             assert isinstance(e, TemplateError)
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(InheritanceTestCase))
-    suite.addTest(unittest.makeSuite(BugFixTestCase))
-    return suite
similarity index 69%
rename from jinja2/testsuite/lexnparse.py
rename to jinja2/testsuite/test_lexnparse.py
index 8ca0b7c8351cf7e70fb48425ea85db0f661fd2cf..ff334bf0ca8b080ec33744997bcf6fef565de278 100644 (file)
@@ -8,9 +8,7 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Environment, Template, TemplateSyntaxError, \
      UndefinedError, nodes
@@ -18,8 +16,6 @@ from jinja2._compat import iteritems, text_type, PY2
 from jinja2.lexer import Token, TokenStream, TOKEN_EOF, \
      TOKEN_BLOCK_BEGIN, TOKEN_BLOCK_END
 
-env = Environment()
-
 
 # how does a string look like in jinja syntax?
 if PY2:
@@ -29,12 +25,14 @@ else:
     jinja_string_repr = repr
 
 
-class TokenStreamTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.tokenstream
+class TestTokenStream():
     test_tokens = [Token(1, TOKEN_BLOCK_BEGIN, ''),
                    Token(2, TOKEN_BLOCK_END, ''),
-                  ]
+                   ]
 
-    def test_simple(self):
+    def test_simple(self, env):
         ts = TokenStream(self.test_tokens, "foo", "bar")
         assert ts.current.type is TOKEN_BLOCK_BEGIN
         assert bool(ts)
@@ -48,29 +46,35 @@ class TokenStreamTestCase(JinjaTestCase):
         assert not bool(ts)
         assert bool(ts.eos)
 
-    def test_iter(self):
-        token_types = [t.type for t in TokenStream(self.test_tokens, "foo", "bar")]
+    def test_iter(self, env):
+        token_types = [
+            t.type for t in TokenStream(self.test_tokens, "foo", "bar")
+        ]
         assert token_types == ['block_begin', 'block_end', ]
 
 
-class LexerTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.lexer
+class TestLexer():
 
-    def test_raw1(self):
-        tmpl = env.from_string('{% raw %}foo{% endraw %}|'
-                               '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
+    def test_raw1(self, env):
+        tmpl = env.from_string(
+            '{% raw %}foo{% endraw %}|'
+            '{%raw%}{{ bar }}|{% baz %}{%       endraw    %}')
         assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
 
-    def test_raw2(self):
+    def test_raw2(self, env):
         tmpl = env.from_string('1  {%- raw -%}   2   {%- endraw -%}   3')
         assert tmpl.render() == '123'
 
-    def test_balancing(self):
+    def test_balancing(self, env):
         env = Environment('{%', '%}', '${', '}')
         tmpl = env.from_string('''{% for item in seq
             %}${{'foo': item}|upper}{% endfor %}''')
-        assert tmpl.render(seq=list(range(3))) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+        assert tmpl.render(seq=list(range(3))) \
+            == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
 
-    def test_comments(self):
+    def test_comments(self, env):
         env = Environment('<!--', '-->', '{', '}')
         tmpl = env.from_string('''\
 <ul>
@@ -78,21 +82,21 @@ class LexerTestCase(JinjaTestCase):
   <li>{item}</li>
 <!--- endfor -->
 </ul>''')
-        assert tmpl.render(seq=list(range(3))) == ("<ul>\n  <li>0</li>\n  "
-                                             "<li>1</li>\n  <li>2</li>\n</ul>")
+        assert tmpl.render(seq=list(range(3))) \
+            == ("<ul>\n  <li>0</li>\n  ""<li>1</li>\n  <li>2</li>\n</ul>")
 
-    def test_string_escapes(self):
+    def test_string_escapes(self, env):
         for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
             tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
             assert tmpl.render() == char
         assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
 
-    def test_bytefallback(self):
+    def test_bytefallback(self, env):
         from pprint import pformat
         tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
         assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
 
-    def test_operators(self):
+    def test_operators(self, env):
         from jinja2.lexer import operators
         for test, expect in iteritems(operators):
             if test in '([{}])':
@@ -101,17 +105,17 @@ class LexerTestCase(JinjaTestCase):
             next(stream)
             assert stream.current.type == expect
 
-    def test_normalizing(self):
+    def test_normalizing(self, env):
         for seq in '\r', '\r\n', '\n':
             env = Environment(newline_sequence=seq)
             tmpl = env.from_string('1\n2\r\n3\n4\n')
             result = tmpl.render()
             assert result.replace(seq, 'X') == '1X2X3X4'
 
-    def test_trailing_newline(self):
+    def test_trailing_newline(self, env):
         for keep in [True, False]:
             env = Environment(keep_trailing_newline=keep)
-            for template,expected in [
+            for template, expected in [
                     ('', {}),
                     ('no\nnewline', {}),
                     ('with\nnewline\n', {False: 'with\nnewline'}),
@@ -122,9 +126,12 @@ class LexerTestCase(JinjaTestCase):
                 result = tmpl.render()
                 assert result == expect, (keep, template, result, expect)
 
-class ParserTestCase(JinjaTestCase):
 
-    def test_php_syntax(self):
+@pytest.mark.lexnparse
+@pytest.mark.parser
+class TestParser():
+
+    def test_php_syntax(self, env):
         env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
         tmpl = env.from_string('''\
 <!-- I'm a comment, I'm not interesting -->\
@@ -133,7 +140,7 @@ class ParserTestCase(JinjaTestCase):
 <?- endfor ?>''')
         assert tmpl.render(seq=list(range(5))) == '01234'
 
-    def test_erb_syntax(self):
+    def test_erb_syntax(self, env):
         env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
         tmpl = env.from_string('''\
 <%# I'm a comment, I'm not interesting %>\
@@ -142,7 +149,7 @@ class ParserTestCase(JinjaTestCase):
 <%- endfor %>''')
         assert tmpl.render(seq=list(range(5))) == '01234'
 
-    def test_comment_syntax(self):
+    def test_comment_syntax(self, env):
         env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
         tmpl = env.from_string('''\
 <!--# I'm a comment, I'm not interesting -->\
@@ -151,26 +158,27 @@ class ParserTestCase(JinjaTestCase):
 <!--- endfor -->''')
         assert tmpl.render(seq=list(range(5))) == '01234'
 
-    def test_balancing(self):
+    def test_balancing(self, env):
         tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
         assert tmpl.render() == 'bar'
 
-    def test_start_comment(self):
+    def test_start_comment(self, env):
         tmpl = env.from_string('''{# foo comment
 and bar comment #}
 {% macro blub() %}foo{% endmacro %}
 {{ blub() }}''')
         assert tmpl.render().strip() == 'foo'
 
-    def test_line_syntax(self):
+    def test_line_syntax(self, env):
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
         tmpl = env.from_string('''\
 <%# regular comment %>
 % for item in seq:
     ${item}
 % endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \
-               list(range(5))
+        assert [
+            int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+        ] == list(range(5))
 
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
         tmpl = env.from_string('''\
@@ -178,10 +186,11 @@ and bar comment #}
 % for item in seq:
     ${item} ## the rest of the stuff
 % endfor''')
-        assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \
-                list(range(5))
+        assert [
+            int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+        ] == list(range(5))
 
-    def test_line_syntax_priority(self):
+    def test_line_syntax_priority(self, env):
         # XXX: why is the whitespace there in front of the newline?
         env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
         tmpl = env.from_string('''\
@@ -201,7 +210,7 @@ and bar comment #}
 # endfor''')
         assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
 
-    def test_error_messages(self):
+    def test_error_messages(self, env):
         def assert_error(code, expected):
             try:
                 Template(code)
@@ -214,10 +223,11 @@ and bar comment #}
                      "Encountered unknown tag 'endif'. Jinja was looking "
                      "for the following tags: 'endfor' or 'else'. The "
                      "innermost block that needs to be closed is 'for'.")
-        assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
-                     "Encountered unknown tag 'endfor'. Jinja was looking for "
-                     "the following tags: 'elif' or 'else' or 'endif'. The "
-                     "innermost block that needs to be closed is 'if'.")
+        assert_error(
+            '{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+            "Encountered unknown tag 'endfor'. Jinja was looking for "
+            "the following tags: 'elif' or 'else' or 'endif'. The "
+            "innermost block that needs to be closed is 'if'.")
         assert_error('{% if foo %}',
                      "Unexpected end of template. Jinja was looking for the "
                      "following tags: 'elif' or 'else' or 'endif'. The "
@@ -226,95 +236,101 @@ and bar comment #}
                      "Unexpected end of template. Jinja was looking for the "
                      "following tags: 'endfor' or 'else'. The innermost block "
                      "that needs to be closed is 'for'.")
-        assert_error('{% block foo-bar-baz %}',
-                     "Block names in Jinja have to be valid Python identifiers "
-                     "and may not contain hyphens, use an underscore instead.")
+        assert_error(
+            '{% block foo-bar-baz %}',
+            "Block names in Jinja have to be valid Python identifiers "
+            "and may not contain hyphens, use an underscore instead.")
         assert_error('{% unknown_tag %}',
                      "Encountered unknown tag 'unknown_tag'.")
 
 
-class SyntaxTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.syntax
+class TestSyntax():
 
-    def test_call(self):
+    def test_call(self, env):
         env = Environment()
         env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
-        tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
+        tmpl = env.from_string(
+            "{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}"
+        )
         assert tmpl.render() == 'abdfh'
 
-    def test_slicing(self):
+    def test_slicing(self, env):
         tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
         assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
 
-    def test_attr(self):
+    def test_attr(self, env):
         tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
         assert tmpl.render(foo={'bar': 42}) == '42|42'
 
-    def test_subscript(self):
+    def test_subscript(self, env):
         tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
         assert tmpl.render(foo=[0, 1, 2]) == '0|2'
 
-    def test_tuple(self):
+    def test_tuple(self, env):
         tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
         assert tmpl.render() == '()|(1,)|(1, 2)'
 
-    def test_math(self):
+    def test_math(self, env):
         tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
         assert tmpl.render() == '1.5|8'
 
-    def test_div(self):
+    def test_div(self, env):
         tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
         assert tmpl.render() == '1|1.5|1'
 
-    def test_unary(self):
+    def test_unary(self, env):
         tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
         assert tmpl.render() == '3|-3'
 
-    def test_concat(self):
+    def test_concat(self, env):
         tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
         assert tmpl.render() == '[1, 2]foo'
 
-    def test_compare(self):
+    def test_compare(self, env):
         tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
                                '{{ 2 == 2 }}|{{ 1 <= 1 }}')
         assert tmpl.render() == 'True|True|True|True|True'
 
-    def test_inop(self):
+    def test_inop(self, env):
         tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
         assert tmpl.render() == 'True|False'
 
-    def test_literals(self):
+    def test_literals(self, env):
         tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
         assert tmpl.render().lower() == '[]|{}|()'
 
-    def test_bool(self):
+    def test_bool(self, env):
         tmpl = env.from_string('{{ true and false }}|{{ false '
                                'or true }}|{{ not false }}')
         assert tmpl.render() == 'False|True|True'
 
-    def test_grouping(self):
-        tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
+    def test_grouping(self, env):
+        tmpl = env.from_string(
+            '{{ (true and false) or (false and true) and not false }}')
         assert tmpl.render() == 'False'
 
-    def test_django_attr(self):
+    def test_django_attr(self, env):
         tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
         assert tmpl.render() == '1|1'
 
-    def test_conditional_expression(self):
+    def test_conditional_expression(self, env):
         tmpl = env.from_string('''{{ 0 if true else 1 }}''')
         assert tmpl.render() == '0'
 
-    def test_short_conditional_expression(self):
+    def test_short_conditional_expression(self, env):
         tmpl = env.from_string('<{{ 1 if false }}>')
         assert tmpl.render() == '<>'
 
         tmpl = env.from_string('<{{ (1 if false).bar }}>')
-        self.assert_raises(UndefinedError, tmpl.render)
+        pytest.raises(UndefinedError, tmpl.render)
 
-    def test_filter_priority(self):
+    def test_filter_priority(self, env):
         tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
         assert tmpl.render() == 'FOOBAR'
 
-    def test_function_calls(self):
+    def test_function_calls(self, env):
         tests = [
             (True, '*foo, bar'),
             (True, '*foo, *bar'),
@@ -329,12 +345,12 @@ class SyntaxTestCase(JinjaTestCase):
         ]
         for should_fail, sig in tests:
             if should_fail:
-                self.assert_raises(TemplateSyntaxError,
-                    env.from_string, '{{ foo(%s) }}' % sig)
+                pytest.raises(TemplateSyntaxError,
+                              env.from_string, '{{ foo(%s) }}' % sig)
             else:
                 env.from_string('foo(%s)' % sig)
 
-    def test_tuple_expr(self):
+    def test_tuple_expr(self, env):
         for tmpl in [
             '{{ () }}',
             '{{ (1, 2) }}',
@@ -347,169 +363,175 @@ class SyntaxTestCase(JinjaTestCase):
         ]:
             assert env.from_string(tmpl)
 
-    def test_trailing_comma(self):
+    def test_trailing_comma(self, env):
         tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
         assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
 
-    def test_block_end_name(self):
+    def test_block_end_name(self, env):
         env.from_string('{% block foo %}...{% endblock foo %}')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{% block x %}{% endblock y %}')
+        pytest.raises(TemplateSyntaxError, env.from_string,
+                      '{% block x %}{% endblock y %}')
 
-    def test_constant_casing(self):
+    def test_constant_casing(self, env):
         for const in True, False, None:
             tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
                 str(const), str(const).lower(), str(const).upper()
             ))
             assert tmpl.render() == '%s|%s|' % (const, const)
 
-    def test_test_chaining(self):
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '{{ foo is string is sequence }}')
-        assert env.from_string('{{ 42 is string or 42 is number }}'
-            ).render() == 'True'
+    def test_test_chaining(self, env):
+        pytest.raises(TemplateSyntaxError, env.from_string,
+                      '{{ foo is string is sequence }}')
+        assert env.from_string(
+            '{{ 42 is string or 42 is number }}'
+        ).render() == 'True'
 
-    def test_string_concatenation(self):
+    def test_string_concatenation(self, env):
         tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
         assert tmpl.render() == 'foobarbaz'
 
-    def test_notin(self):
+    def test_notin(self, env):
         bar = range(100)
         tmpl = env.from_string('''{{ not 42 in bar }}''')
         assert tmpl.render(bar=bar) == text_type(not 42 in bar)
 
-    def test_implicit_subscribed_tuple(self):
+    def test_implicit_subscribed_tuple(self, env):
         class Foo(object):
             def __getitem__(self, x):
                 return x
         t = env.from_string('{{ foo[1, 2] }}')
         assert t.render(foo=Foo()) == u'(1, 2)'
 
-    def test_raw2(self):
+    def test_raw2(self, env):
         tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
         assert tmpl.render() == '{{ FOO }} and {% BAR %}'
 
-    def test_const(self):
-        tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
-                               '{{ none is defined }}|{{ missing is defined }}')
+    def test_const(self, env):
+        tmpl = env.from_string(
+            '{{ true }}|{{ false }}|{{ none }}|'
+            '{{ none is defined }}|{{ missing is defined }}')
         assert tmpl.render() == 'True|False|None|True|False'
 
-    def test_neg_filter_priority(self):
+    def test_neg_filter_priority(self, env):
         node = env.parse('{{ -1|foo }}')
         assert isinstance(node.body[0].nodes[0], nodes.Filter)
         assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
 
-    def test_const_assign(self):
+    def test_const_assign(self, env):
         constass1 = '''{% set true = 42 %}'''
         constass2 = '''{% for none in seq %}{% endfor %}'''
         for tmpl in constass1, constass2:
-            self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
+            pytest.raises(TemplateSyntaxError, env.from_string, tmpl)
 
-    def test_localset(self):
+    def test_localset(self, env):
         tmpl = env.from_string('''{% set foo = 0 %}\
 {% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
 {{ foo }}''')
         assert tmpl.render() == '0'
 
-    def test_parse_unary(self):
+    def test_parse_unary(self, env):
         tmpl = env.from_string('{{ -foo["bar"] }}')
         assert tmpl.render(foo={'bar': 42}) == '-42'
         tmpl = env.from_string('{{ -foo["bar"]|abs }}')
         assert tmpl.render(foo={'bar': 42}) == '42'
 
 
-class LstripBlocksTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.lstripblocks
+class TestLstripBlocks():
 
-    def test_lstrip(self):
+    def test_lstrip(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    {% if True %}\n    {% endif %}''')
         assert tmpl.render() == "\n"
 
-    def test_lstrip_trim(self):
+    def test_lstrip_trim(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''    {% if True %}\n    {% endif %}''')
         assert tmpl.render() == ""
 
-    def test_no_lstrip(self):
+    def test_no_lstrip(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    {%+ if True %}\n    {%+ endif %}''')
         assert tmpl.render() == "    \n    "
 
-    def test_lstrip_endline(self):
+    def test_lstrip_endline(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
-        tmpl = env.from_string('''    hello{% if True %}\n    goodbye{% endif %}''')
+        tmpl = env.from_string(
+            '''    hello{% if True %}\n    goodbye{% endif %}''')
         assert tmpl.render() == "    hello\n    goodbye"
 
-    def test_lstrip_inline(self):
+    def test_lstrip_inline(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    {% if True %}hello    {% endif %}''')
         assert tmpl.render() == 'hello    '
 
-    def test_lstrip_nested(self):
+    def test_lstrip_nested(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
-        tmpl = env.from_string('''    {% if True %}a {% if True %}b {% endif %}c {% endif %}''')
+        tmpl = env.from_string(
+            '''    {% if True %}a {% if True %}b {% endif %}c {% endif %}''')
         assert tmpl.render() == 'a b c '
 
-    def test_lstrip_left_chars(self):
+    def test_lstrip_left_chars(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    abc {% if True %}
         hello{% endif %}''')
         assert tmpl.render() == '    abc \n        hello'
 
-    def test_lstrip_embeded_strings(self):
+    def test_lstrip_embeded_strings(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    {% set x = " {% str %} " %}{{ x }}''')
         assert tmpl.render() == ' {% str %} '
 
-    def test_lstrip_preserve_leading_newlines(self):
+    def test_lstrip_preserve_leading_newlines(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''\n\n\n{% set hello = 1 %}''')
         assert tmpl.render() == '\n\n\n'
-        
-    def test_lstrip_comment(self):
+
+    def test_lstrip_comment(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
         tmpl = env.from_string('''    {# if True #}
 hello
     {#endif#}''')
         assert tmpl.render() == '\nhello\n'
 
-    def test_lstrip_angle_bracket_simple(self):
+    def test_lstrip_angle_bracket_simple(self, env):
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''    <% if True %>hello    <% endif %>''')
         assert tmpl.render() == 'hello    '
 
-    def test_lstrip_angle_bracket_comment(self):
+    def test_lstrip_angle_bracket_comment(self, env):
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''    <%# if True %>hello    <%# endif %>''')
         assert tmpl.render() == 'hello    '
 
-    def test_lstrip_angle_bracket(self):
+    def test_lstrip_angle_bracket(self, env):
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
     <%# regular comment %>
     <% for item in seq %>
 ${item} ## the rest of the stuff
    <% endfor %>''')
         assert tmpl.render(seq=range(5)) == \
-                ''.join('%s\n' % x for x in range(5))
-        
-    def test_lstrip_angle_bracket_compact(self):
+            ''.join('%s\n' % x for x in range(5))
+
+    def test_lstrip_angle_bracket_compact(self, env):
         env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
     <%#regular comment%>
     <%for item in seq%>
 ${item} ## the rest of the stuff
    <%endfor%>''')
         assert tmpl.render(seq=range(5)) == \
-                ''.join('%s\n' % x for x in range(5))
-        
-    def test_php_syntax_with_manual(self):
+            ''.join('%s\n' % x for x in range(5))
+
+    def test_php_syntax_with_manual(self, env):
         env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
     <!-- I'm a comment, I'm not interesting -->
     <? for item in seq -?>
@@ -517,45 +539,48 @@ ${item} ## the rest of the stuff
     <?- endfor ?>''')
         assert tmpl.render(seq=range(5)) == '01234'
 
-    def test_php_syntax(self):
+    def test_php_syntax(self, env):
         env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
     <!-- I'm a comment, I'm not interesting -->
     <? for item in seq ?>
         <?= item ?>
     <? endfor ?>''')
-        assert tmpl.render(seq=range(5)) == ''.join('        %s\n' % x for x in range(5))
+        assert tmpl.render(seq=range(5)) \
+            == ''.join('        %s\n' % x for x in range(5))
 
-    def test_php_syntax_compact(self):
+    def test_php_syntax_compact(self, env):
         env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
     <!-- I'm a comment, I'm not interesting -->
     <?for item in seq?>
         <?=item?>
     <?endfor?>''')
-        assert tmpl.render(seq=range(5)) == ''.join('        %s\n' % x for x in range(5))
+        assert tmpl.render(seq=range(5)) \
+            == ''.join('        %s\n' % x for x in range(5))
 
-    def test_erb_syntax(self):
+    def test_erb_syntax(self, env):
         env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
-            lstrip_blocks=True, trim_blocks=True)
-        #env.from_string('')
-        #for n,r in env.lexer.rules.iteritems():
+                          lstrip_blocks=True, trim_blocks=True)
+        # env.from_string('')
+        # for n,r in env.lexer.rules.iteritems():
         #    print n
-        #print env.lexer.rules['root'][0][0].pattern
-        #print "'%s'" % tmpl.render(seq=range(5))
+        # print env.lexer.rules['root'][0][0].pattern
+        # print "'%s'" % tmpl.render(seq=range(5))
         tmpl = env.from_string('''\
 <%# I'm a comment, I'm not interesting %>
     <% for item in seq %>
     <%= item %>
     <% endfor %>
 ''')
-        assert tmpl.render(seq=range(5)) == ''.join('    %s\n' % x for x in range(5))
+        assert tmpl.render(seq=range(5)) \
+            == ''.join('    %s\n' % x for x in range(5))
 
-    def test_erb_syntax_with_manual(self):
+    def test_erb_syntax_with_manual(self, env):
         env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
 <%# I'm a comment, I'm not interesting %>
     <% for item in seq -%>
@@ -563,9 +588,9 @@ ${item} ## the rest of the stuff
     <%- endfor %>''')
         assert tmpl.render(seq=range(5)) == '01234'
 
-    def test_erb_syntax_no_lstrip(self):
+    def test_erb_syntax_no_lstrip(self, env):
         env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
 <%# I'm a comment, I'm not interesting %>
     <%+ for item in seq -%>
@@ -573,21 +598,12 @@ ${item} ## the rest of the stuff
     <%- endfor %>''')
         assert tmpl.render(seq=range(5)) == '    01234'
 
-    def test_comment_syntax(self):
+    def test_comment_syntax(self, env):
         env = Environment('<!--', '-->', '${', '}', '<!--#', '-->',
-            lstrip_blocks=True, trim_blocks=True)
+                          lstrip_blocks=True, trim_blocks=True)
         tmpl = env.from_string('''\
 <!--# I'm a comment, I'm not interesting -->\
 <!-- for item in seq --->
     ${item}
 <!--- endfor -->''')
         assert tmpl.render(seq=range(5)) == '01234'
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(TokenStreamTestCase))
-    suite.addTest(unittest.makeSuite(LexerTestCase))
-    suite.addTest(unittest.makeSuite(ParserTestCase))
-    suite.addTest(unittest.makeSuite(SyntaxTestCase))
-    suite.addTest(unittest.makeSuite(LstripBlocksTestCase))
-    return suite
similarity index 69%
rename from jinja2/testsuite/loader.py
rename to jinja2/testsuite/test_loader.py
index 73a7f3005966010d06a4e6ca5e8b3a044ccac419..7a8bba5bb42e3f1ee70527866b326afafbd2e537 100644 (file)
@@ -12,64 +12,63 @@ import os
 import sys
 import tempfile
 import shutil
+import pytest
 import unittest
 
-from jinja2.testsuite import JinjaTestCase, dict_loader, \
-     package_loader, filesystem_loader, function_loader, \
-     choice_loader, prefix_loader
-
 from jinja2 import Environment, loaders
 from jinja2._compat import PYPY, PY2
 from jinja2.loaders import split_template_path
 from jinja2.exceptions import TemplateNotFound
 
 
-class LoaderTestCase(JinjaTestCase):
+@pytest.mark.loaders
+class TestLoaders():
 
-    def test_dict_loader(self):
+    def test_dict_loader(self, dict_loader):
         env = Environment(loader=dict_loader)
         tmpl = env.get_template('justdict.html')
         assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
 
-    def test_package_loader(self):
+    def test_package_loader(self, package_loader):
         env = Environment(loader=package_loader)
         tmpl = env.get_template('test.html')
         assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
 
-    def test_filesystem_loader(self):
+    def test_filesystem_loader(self, filesystem_loader):
         env = Environment(loader=filesystem_loader)
         tmpl = env.get_template('test.html')
         assert tmpl.render().strip() == 'BAR'
         tmpl = env.get_template('foo/test.html')
         assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
 
-    def test_choice_loader(self):
+    def test_choice_loader(self, choice_loader):
         env = Environment(loader=choice_loader)
         tmpl = env.get_template('justdict.html')
         assert tmpl.render().strip() == 'FOO'
         tmpl = env.get_template('test.html')
         assert tmpl.render().strip() == 'BAR'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
 
-    def test_function_loader(self):
+    def test_function_loader(self, function_loader):
         env = Environment(loader=function_loader)
         tmpl = env.get_template('justfunction.html')
         assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
 
-    def test_prefix_loader(self):
+    def test_prefix_loader(self, prefix_loader):
         env = Environment(loader=prefix_loader)
         tmpl = env.get_template('a/test.html')
         assert tmpl.render().strip() == 'BAR'
         tmpl = env.get_template('b/justdict.html')
         assert tmpl.render().strip() == 'FOO'
-        self.assert_raises(TemplateNotFound, env.get_template, 'missing')
+        pytest.raises(TemplateNotFound, env.get_template, 'missing')
 
     def test_caching(self):
         changed = False
+
         class TestLoader(loaders.BaseLoader):
             def get_source(self, environment, template):
                 return u'foo', None, lambda: not changed
@@ -82,7 +81,7 @@ class LoaderTestCase(JinjaTestCase):
 
         env = Environment(loader=TestLoader(), cache_size=0)
         assert env.get_template('template') \
-               is not env.get_template('template')
+            is not env.get_template('template')
 
         env = Environment(loader=TestLoader(), cache_size=2)
         t1 = env.get_template('one')
@@ -104,14 +103,15 @@ class LoaderTestCase(JinjaTestCase):
     def test_split_template_path(self):
         assert split_template_path('foo/bar') == ['foo', 'bar']
         assert split_template_path('./foo/bar') == ['foo', 'bar']
-        self.assert_raises(TemplateNotFound, split_template_path, '../foo')
+        pytest.raises(TemplateNotFound, split_template_path, '../foo')
 
 
-class ModuleLoaderTestCase(JinjaTestCase):
+@pytest.mark.loaders
+@pytest.mark.moduleloader
+class TestModuleLoader():
     archive = None
 
-    def compile_down(self, zip='deflated', py_compile=False):
-        super(ModuleLoaderTestCase, self).setup()
+    def compile_down(self, prefix_loader, zip='deflated', py_compile=False):
         log = []
         self.reg_env = Environment(loader=prefix_loader)
         if zip is not None:
@@ -126,7 +126,6 @@ class ModuleLoaderTestCase(JinjaTestCase):
         return ''.join(log)
 
     def teardown(self):
-        super(ModuleLoaderTestCase, self).teardown()
         if hasattr(self, 'mod_env'):
             if os.path.isfile(self.archive):
                 os.remove(self.archive)
@@ -134,8 +133,8 @@ class ModuleLoaderTestCase(JinjaTestCase):
                 shutil.rmtree(self.archive)
             self.archive = None
 
-    def test_log(self):
-        log = self.compile_down()
+    def test_log(self, prefix_loader):
+        log = self.compile_down(prefix_loader)
         assert 'Compiled "a/foo/test.html" as ' \
                'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
         assert 'Finished compiling templates' in log
@@ -151,20 +150,20 @@ class ModuleLoaderTestCase(JinjaTestCase):
         tmpl2 = self.mod_env.get_template('b/justdict.html')
         assert tmpl1.render() == tmpl2.render()
 
-    def test_deflated_zip_compile(self):
-        self.compile_down(zip='deflated')
+    def test_deflated_zip_compile(self, prefix_loader):
+        self.compile_down(prefix_loader, zip='deflated')
         self._test_common()
 
-    def test_stored_zip_compile(self):
-        self.compile_down(zip='stored')
+    def test_stored_zip_compile(self, prefix_loader):
+        self.compile_down(prefix_loader, zip='stored')
         self._test_common()
 
-    def test_filesystem_compile(self):
-        self.compile_down(zip=None)
+    def test_filesystem_compile(self, prefix_loader):
+        self.compile_down(prefix_loader, zip=None)
         self._test_common()
 
-    def test_weak_references(self):
-        self.compile_down()
+    def test_weak_references(self, prefix_loader):
+        self.compile_down(prefix_loader)
         tmpl = self.mod_env.get_template('a/test.html')
         key = loaders.ModuleLoader.get_template_key('a/test.html')
         name = self.mod_env.loader.module.__name__
@@ -184,17 +183,19 @@ class ModuleLoaderTestCase(JinjaTestCase):
         assert name not in sys.modules
 
     # This test only makes sense on non-pypy python 2
-    if PY2 and not PYPY:
-        def test_byte_compilation(self):
-            log = self.compile_down(py_compile=True)
-            assert 'Byte-compiled "a/test.html"' in log
-            tmpl1 = self.mod_env.get_template('a/test.html')
-            mod = self.mod_env.loader.module. \
-                tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
-            assert mod.__file__.endswith('.pyc')
-
-    def test_choice_loader(self):
-        log = self.compile_down()
+    @pytest.mark.skipif(
+        not (PY2 and not PYPY),
+        reason='This test only makes sense on non-pypy python 2')
+    def test_byte_compilation(self, prefix_loader):
+        log = self.compile_down(prefix_loader, py_compile=True)
+        assert 'Byte-compiled "a/test.html"' in log
+        tmpl1 = self.mod_env.get_template('a/test.html')
+        mod = self.mod_env.loader.module. \
+            tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+        assert mod.__file__.endswith('.pyc')
+
+    def test_choice_loader(self, prefix_loader):
+        log = self.compile_down(prefix_loader)
 
         self.mod_env.loader = loaders.ChoiceLoader([
             self.mod_env.loader,
@@ -202,12 +203,12 @@ class ModuleLoaderTestCase(JinjaTestCase):
         ])
 
         tmpl1 = self.mod_env.get_template('a/test.html')
-        self.assert_equal(tmpl1.render(), 'BAR')
+        assert tmpl1.render() == 'BAR'
         tmpl2 = self.mod_env.get_template('DICT_SOURCE')
-        self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
+        assert tmpl2.render() == 'DICT_TEMPLATE'
 
-    def test_prefix_loader(self):
-        log = self.compile_down()
+    def test_prefix_loader(self, prefix_loader):
+        log = self.compile_down(prefix_loader)
 
         self.mod_env.loader = loaders.PrefixLoader({
             'MOD':      self.mod_env.loader,
@@ -215,13 +216,6 @@ class ModuleLoaderTestCase(JinjaTestCase):
         })
 
         tmpl1 = self.mod_env.get_template('MOD/a/test.html')
-        self.assert_equal(tmpl1.render(), 'BAR')
+        assert tmpl1.render() == 'BAR'
         tmpl2 = self.mod_env.get_template('DICT/test.html')
-        self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LoaderTestCase))
-    suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
-    return suite
+        assert tmpl2.render() == 'DICT_TEMPLATE'
similarity index 74%
rename from jinja2/testsuite/regression.py
rename to jinja2/testsuite/test_regression.py
index c5f7d5c659c8ecc2bbc725953fb1904b64b36a96..a4aa157110395fcd24997bc04a7022f706d00560 100644 (file)
@@ -8,20 +8,17 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
      TemplateNotFound, PrefixLoader
 from jinja2._compat import text_type
 
-env = Environment()
-
 
-class CornerTestCase(JinjaTestCase):
+@pytest.mark.regression
+class TestCorner():
 
-    def test_assigned_scoping(self):
+    def test_assigned_scoping(self, env):
         t = env.from_string('''
         {%- for item in (1, 2, 3, 4) -%}
             [{{ item }}]
@@ -48,7 +45,7 @@ class CornerTestCase(JinjaTestCase):
         ''')
         assert t.render() == '[1][2][3][4]42'
 
-    def test_closure_scoping(self):
+    def test_closure_scoping(self, env):
         t = env.from_string('''
         {%- set wrapper = "<FOO>" %}
         {%- for item in (1, 2, 3, 4) %}
@@ -79,30 +76,34 @@ class CornerTestCase(JinjaTestCase):
         assert t.render(wrapper=23) == '[1][2][3][4]23'
 
 
-class BugTestCase(JinjaTestCase):
+@pytest.mark.regression
+class TestBug():
 
-    def test_keyword_folding(self):
+    def test_keyword_folding(self, env):
         env = Environment()
         env.filters['testing'] = lambda value, some: value + some
         assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
-               .render() == 'teststuff'
+            .render() == 'teststuff'
 
-    def test_extends_output_bugs(self):
+    def test_extends_output_bugs(self, env):
         env = Environment(loader=DictLoader({
             'parent.html': '(({% block title %}{% endblock %}))'
         }))
 
-        t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
-                            '[[{% block title %}title{% endblock %}]]'
-                            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+        t = env.from_string(
+            '{% if expr %}{% extends "parent.html" %}{% endif %}'
+            '[[{% block title %}title{% endblock %}]]'
+            '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}'
+        )
         assert t.render(expr=False) == '[[title]](1)(2)(3)'
         assert t.render(expr=True) == '((title))'
 
-    def test_urlize_filter_escaping(self):
+    def test_urlize_filter_escaping(self, env):
         tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
-        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
+        assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">'\
+            'http://www.example.org/&lt;foo</a>'
 
-    def test_loop_call_loop(self):
+    def test_loop_call_loop(self, env):
         tmpl = env.from_string('''
 
         {% macro test() %}
@@ -119,24 +120,25 @@ class BugTestCase(JinjaTestCase):
 
         ''')
 
-        assert tmpl.render().split() == [text_type(x) for x in range(1, 11)] * 5
+        assert tmpl.render().split() \
+            == [text_type(x) for x in range(1, 11)] * 5
 
-    def test_weird_inline_comment(self):
+    def test_weird_inline_comment(self, env):
         env = Environment(line_statement_prefix='%')
-        self.assert_raises(TemplateSyntaxError, env.from_string,
-                           '% for item in seq {# missing #}\n...% endfor')
+        pytest.raises(TemplateSyntaxError, env.from_string,
+                      '% for item in seq {# missing #}\n...% endfor')
 
-    def test_old_macro_loop_scoping_bug(self):
+    def test_old_macro_loop_scoping_bug(self, env):
         tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
                                '{% macro i() %}3{% endmacro %}{{ i() }}')
         assert tmpl.render() == '123'
 
-    def test_partial_conditional_assignments(self):
+    def test_partial_conditional_assignments(self, env):
         tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
         assert tmpl.render(a=23) == '23'
         assert tmpl.render(b=True) == '42'
 
-    def test_stacked_locals_scoping_bug(self):
+    def test_stacked_locals_scoping_bug(self, env):
         env = Environment(line_statement_prefix='#')
         t = env.from_string('''\
 # for j in [1, 2]:
@@ -160,7 +162,7 @@ class BugTestCase(JinjaTestCase):
     ''')
         assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
 
-    def test_stacked_locals_scoping_bug_twoframe(self):
+    def test_stacked_locals_scoping_bug_twoframe(self, env):
         t = Template('''
             {% set x = 1 %}
             {% for item in foo %}
@@ -173,7 +175,7 @@ class BugTestCase(JinjaTestCase):
         rv = t.render(foo=[1]).strip()
         assert rv == u'1'
 
-    def test_call_with_args(self):
+    def test_call_with_args(self, env):
         t = Template("""{% macro dump_users(users) -%}
         <ul>
           {%- for user in users -%}
@@ -192,9 +194,9 @@ class BugTestCase(JinjaTestCase):
         {% endcall %}""")
 
         assert [x.strip() for x in t.render(list_of_user=[{
-            'username':'apo',
-            'realname':'something else',
-            'description':'test'
+            'username': 'apo',
+            'realname': 'something else',
+            'description': 'test'
         }]).splitlines()] == [
             u'<ul><li><p>apo</p><dl>',
             u'<dl>Realname</dl>',
@@ -205,12 +207,15 @@ class BugTestCase(JinjaTestCase):
             u'</li></ul>'
         ]
 
-    def test_empty_if_condition_fails(self):
-        self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
-        self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
+    def test_empty_if_condition_fails(self, env):
+        pytest.raises(TemplateSyntaxError,
+                      Template, '{% if %}....{% endif %}')
+        pytest.raises(TemplateSyntaxError,
+                      Template, '{% if foo %}...{% elif %}...{% endif %}')
+        pytest.raises(TemplateSyntaxError,
+                      Template, '{% for x in %}..{% endfor %}')
 
-    def test_recursive_loop_bug(self):
+    def test_recursive_loop_bug(self, env):
         tpl1 = Template("""
         {% for p in foo recursive%}
             {{p.bar}}
@@ -237,7 +242,7 @@ class BugTestCase(JinjaTestCase):
         {% endfor %}
         """)
 
-    def test_else_loop_bug(self):
+    def test_else_loop_bug(self, env):
         t = Template('''
             {% for x in y %}
                 {{ loop.index0 }}
@@ -245,9 +250,9 @@ class BugTestCase(JinjaTestCase):
                 {% for i in range(3) %}{{ i }}{% endfor %}
             {% endfor %}
         ''')
-        self.assertEqual(t.render(y=[]).strip(), '012')
+        assert t.render(y=[]).strip() == '012'
 
-    def test_correct_prefix_loader_name(self):
+    def test_correct_prefix_loader_name(self, env):
         env = Environment(loader=PrefixLoader({
             'foo':  DictLoader({})
         }))
@@ -258,22 +263,16 @@ class BugTestCase(JinjaTestCase):
         else:
             assert False, 'expected error here'
 
-    def test_contextfunction_callable_classes(self):
+    def test_contextfunction_callable_classes(self, env):
         from jinja2.utils import contextfunction
+
         class CallableClass(object):
             @contextfunction
             def __call__(self, ctx):
                 return ctx.resolve('hello')
 
         tpl = Template("""{{ callableclass() }}""")
-        output = tpl.render(callableclass = CallableClass(), hello = 'TEST')
+        output = tpl.render(callableclass=CallableClass(), hello='TEST')
         expected = 'TEST'
 
-        self.assert_equal(output, expected)
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(CornerTestCase))
-    suite.addTest(unittest.makeSuite(BugTestCase))
-    return suite
+        assert output == expected
similarity index 72%
rename from jinja2/testsuite/security.py
rename to jinja2/testsuite/test_security.py
index 246d0f07394057c4a8e8508e51886f85048e6c7d..e5b463fc989263e372823458f8c605e39d975a53 100644 (file)
@@ -8,9 +8,7 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Environment
 from jinja2.sandbox import SandboxedEnvironment, \
@@ -42,38 +40,40 @@ class PublicStuff(object):
         return 'PublicStuff'
 
 
-class SandboxTestCase(JinjaTestCase):
+@pytest.mark.sandbox
+class TestSandbox():
 
-    def test_unsafe(self):
+    def test_unsafe(self, env):
         env = SandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
-                           foo=PrivateStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
-
-        self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
-                           foo=PublicStuff())
-        self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
-        self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
-        self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
+        pytest.raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+                      foo=PrivateStuff())
+        assert env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()) == '23'
+
+        pytest.raises(SecurityError,
+                      env.from_string("{{ foo._foo() }}").render,
+                      foo=PublicStuff())
+        assert env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()) == '23'
+        assert env.from_string("{{ foo.__class__ }}").render(foo=42) == ''
+        assert env.from_string("{{ foo.func_code }}").render(foo=lambda:None) == ''
         # security error comes from __class__ already.
-        self.assert_raises(SecurityError, env.from_string(
+        pytest.raises(SecurityError, env.from_string(
             "{{ foo.__class__.__subclasses__() }}").render, foo=42)
 
-    def test_immutable_environment(self):
+    def test_immutable_environment(self, env):
         env = ImmutableSandboxedEnvironment()
-        self.assert_raises(SecurityError, env.from_string(
+        pytest.raises(SecurityError, env.from_string(
             '{{ [].append(23) }}').render)
-        self.assert_raises(SecurityError, env.from_string(
+        pytest.raises(SecurityError, env.from_string(
             '{{ {1:2}.clear() }}').render)
 
-    def test_restricted(self):
+    def test_restricted(self, env):
         env = SandboxedEnvironment()
-        self.assert_raises(TemplateSyntaxError, env.from_string,
+        pytest.raises(TemplateSyntaxError, env.from_string,
                       "{% for item.attribute in seq %}...{% endfor %}")
-        self.assert_raises(TemplateSyntaxError, env.from_string,
+        pytest.raises(TemplateSyntaxError, env.from_string,
                       "{% for foo, bar.baz in seq %}...{% endfor %}")
 
-    def test_markup_operations(self):
+    def test_markup_operations(self, env):
         # adding two strings should escape the unsafe one
         unsafe = '<script type="application/x-some-script">alert("foo");</script>'
         safe = Markup('<em>username</em>')
@@ -81,7 +81,7 @@ class SandboxTestCase(JinjaTestCase):
 
         # string interpolations are safe to use too
         assert Markup('<em>%s</em>') % '<bad user>' == \
-               '<em>&lt;bad user&gt;</em>'
+            '<em>&lt;bad user&gt;</em>'
         assert Markup('<em>%(username)s</em>') % {
             'username': '<bad user>'
         } == '<em>&lt;bad user&gt;</em>'
@@ -97,18 +97,19 @@ class SandboxTestCase(JinjaTestCase):
         class Foo(object):
             def __html__(self):
                 return '<em>awesome</em>'
+
             def __unicode__(self):
                 return 'awesome'
         assert Markup(Foo()) == '<em>awesome</em>'
         assert Markup('<strong>%s</strong>') % Foo() == \
-               '<strong><em>awesome</em></strong>'
+            '<strong><em>awesome</em></strong>'
 
         # escaping and unescaping
         assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
         assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
         assert Markup("&lt;test&gt;").unescape() == "<test>"
 
-    def test_template_data(self):
+    def test_template_data(self, env):
         env = Environment(autoescape=True)
         t = env.from_string('{% macro say_hello(name) %}'
                             '<p>Hello {{ name }}!</p>{% endmacro %}'
@@ -120,12 +121,12 @@ class SandboxTestCase(JinjaTestCase):
         assert t.module.say_hello('<blink>foo</blink>') == escaped_out
         assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
 
-    def test_attr_filter(self):
+    def test_attr_filter(self, env):
         env = SandboxedEnvironment()
         tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}')
-        self.assert_raises(SecurityError, tmpl.render, cls=int)
+        pytest.raises(SecurityError, tmpl.render, cls=int)
 
-    def test_binary_operator_intercepting(self):
+    def test_binary_operator_intercepting(self, env):
         def disable_op(left, right):
             raise TemplateRuntimeError('that operator so does not work')
         for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'):
@@ -140,9 +141,9 @@ class SandboxTestCase(JinjaTestCase):
             except TemplateRuntimeError as e:
                 pass
             else:
-                self.fail('expected runtime error')
+                assert False, 'expected runtime error'
 
-    def test_unary_operator_intercepting(self):
+    def test_unary_operator_intercepting(self, env):
         def disable_op(arg):
             raise TemplateRuntimeError('that operator so does not work')
         for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'):
@@ -157,10 +158,4 @@ class SandboxTestCase(JinjaTestCase):
             except TemplateRuntimeError as e:
                 pass
             else:
-                self.fail('expected runtime error')
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(SandboxTestCase))
-    return suite
+                assert False, 'expected runtime error'
similarity index 80%
rename from jinja2/testsuite/tests.py
rename to jinja2/testsuite/test_tests.py
index 704f06872777d11695f84645c26b6359ae55071c..9e54038c9a2dc18bbdc4069484389e852dfd3cf9 100644 (file)
@@ -8,33 +8,32 @@
     :copyright: (c) 2010 by the Jinja Team.
     :license: BSD, see LICENSE for more details.
 """
-import unittest
-from jinja2.testsuite import JinjaTestCase
+import pytest
 
 from jinja2 import Markup, Environment
 
-env = Environment()
 
+@pytest.mark.test_tests
+class TestTestsCase():
 
-class TestsTestCase(JinjaTestCase):
-
-    def test_defined(self):
-        tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
+    def test_defined(self, env):
+        tmpl = env.from_string('{{ missing is defined }}|'
+                               '{{ true is defined }}')
         assert tmpl.render() == 'False|True'
 
-    def test_even(self):
+    def test_even(self, env):
         tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
         assert tmpl.render() == 'False|True'
 
-    def test_odd(self):
+    def test_odd(self, env):
         tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
         assert tmpl.render() == 'True|False'
 
-    def test_lower(self):
+    def test_lower(self, env):
         tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
         assert tmpl.render() == 'True|False'
 
-    def test_typechecks(self):
+    def test_typechecks(self, env):
         tmpl = env.from_string('''
             {{ 42 is undefined }}
             {{ 42 is defined }}
@@ -56,15 +55,17 @@ class TestsTestCase(JinjaTestCase):
             {{ 3.14159 is number }}
             {{ complex is number }}
         ''')
+
         class MyDict(dict):
             pass
+
         assert tmpl.render(mydict=MyDict(), complex=complex(1, 2)).split() == [
             'False', 'True', 'False', 'True', 'True', 'False',
             'True', 'True', 'True', 'True', 'False', 'True',
             'True', 'True', 'False', 'True', 'True', 'True', 'True'
         ]
 
-    def test_sequence(self):
+    def test_sequence(self, env):
         tmpl = env.from_string(
             '{{ [1, 2, 3] is sequence }}|'
             '{{ "foo" is sequence }}|'
@@ -72,11 +73,11 @@ class TestsTestCase(JinjaTestCase):
         )
         assert tmpl.render() == 'True|True|False'
 
-    def test_upper(self):
+    def test_upper(self, env):
         tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
         assert tmpl.render() == 'True|False'
 
-    def test_equalto(self):
+    def test_equalto(self, env):
         tmpl = env.from_string('{{ foo is equalto 12 }}|'
                                '{{ foo is equalto 0 }}|'
                                '{{ foo is equalto (3 * 4) }}|'
@@ -85,24 +86,19 @@ class TestsTestCase(JinjaTestCase):
                                '{{ bar is equalto ("ba" + "z") }}|'
                                '{{ bar is equalto bar }}|'
                                '{{ bar is equalto foo }}')
-        assert tmpl.render(foo=12, bar="baz") == 'True|False|True|True|False|True|True|False'
+        assert tmpl.render(foo=12, bar="baz") \
+            == 'True|False|True|True|False|True|True|False'
 
-    def test_sameas(self):
+    def test_sameas(self, env):
         tmpl = env.from_string('{{ foo is sameas false }}|'
                                '{{ 0 is sameas false }}')
         assert tmpl.render(foo=False) == 'True|False'
 
-    def test_no_paren_for_arg1(self):
+    def test_no_paren_for_arg1(self, env):
         tmpl = env.from_string('{{ foo is sameas none }}')
         assert tmpl.render(foo=None) == 'True'
 
-    def test_escaped(self):
+    def test_escaped(self, env):
         env = Environment(autoescape=True)
         tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
         assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(TestsTestCase))
-    return suite
similarity index 61%
rename from jinja2/testsuite/utils.py
rename to jinja2/testsuite/test_utils.py
index cab9b09a93d143ed6a981ab66a08c82c59c8c8d4..373103618d2f30897a05c459c08bce22711e133a 100644 (file)
@@ -9,16 +9,17 @@
     :license: BSD, see LICENSE for more details.
 """
 import gc
-import unittest
 
-import pickle
+import pytest
 
-from jinja2.testsuite import JinjaTestCase
+import pickle
 
 from jinja2.utils import LRUCache, escape, object_type_repr
 
 
-class LRUCacheTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.lrucache
+class TestLRUCache():
 
     def test_simple(self):
         d = LRUCache(3)
@@ -43,20 +44,25 @@ class LRUCacheTestCase(JinjaTestCase):
             assert copy._queue == cache._queue
 
 
-class HelpersTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.helpers
+class TestHelpers():
 
     def test_object_type_repr(self):
         class X(object):
             pass
-        self.assert_equal(object_type_repr(42), 'int object')
-        self.assert_equal(object_type_repr([]), 'list object')
-        self.assert_equal(object_type_repr(X()),
-                         'jinja2.testsuite.utils.X object')
-        self.assert_equal(object_type_repr(None), 'None')
-        self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
+        assert object_type_repr(42) == 'int object'
+        assert object_type_repr([]) == 'list object'
+        assert object_type_repr(X()) == 'test_utils.X object'
+        assert object_type_repr(None) == 'None'
+        assert object_type_repr(Ellipsis) == 'Ellipsis'
 
 
-class MarkupLeakTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.markupleak
+@pytest.mark.skipif(hasattr(escape, 'func_code'),
+                    reason='this test only tests the c extension')
+class TestMarkupLeak():
 
     def test_markup_leaks(self):
         counts = set()
@@ -68,15 +74,3 @@ class MarkupLeakTestCase(JinjaTestCase):
                 escape(u"<foo>")
             counts.add(len(gc.get_objects()))
         assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(LRUCacheTestCase))
-    suite.addTest(unittest.makeSuite(HelpersTestCase))
-
-    # this test only tests the c extension
-    if not hasattr(escape, 'func_code'):
-        suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
-    return suite
diff --git a/pytest.ini b/pytest.ini
new file mode 100644 (file)
index 0000000..df3eb51
--- /dev/null
@@ -0,0 +1,2 @@
+[pytest]
+addopts = --doctest-modules
index 3f080b966f90b3eb4b32ce978b40593cb37b2112..2cf3106f0c3edff04e16210570935f539de87480 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -71,10 +71,9 @@ setup(
         'Topic :: Software Development :: Libraries :: Python Modules',
         'Topic :: Text Processing :: Markup :: HTML'
     ],
-    packages=['jinja2', 'jinja2.testsuite', 'jinja2.testsuite.res'],
+    packages=['jinja2'],
     install_requires=['MarkupSafe'],
     extras_require={'i18n': ['Babel>=0.8']},
-    test_suite='jinja2.testsuite.suite',
     include_package_data=True,
     entry_points="""
     [babel.extractors]
diff --git a/tox.ini b/tox.ini
index 8dc90020e44592c02cf40f378aa11af39667e2c5..e02581d1cbac0a65bd6463c2a6ebb55217e84781 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -2,4 +2,4 @@
 envlist = py26, py27, pypy, py33, py34
 
 [testenv]
-commands = python run-tests.py {posargs}
+commands = py.test jinja2