Commits

danjac  committed ea116cd

testing decorators branch

  • Participants
  • Parent commits ebdec97
  • Branches decorators

Comments (0)

Files changed (2)

File flaskext/testing.py

 from werkzeug import cached_property
 from werkzeug import LocalStack, LocalProxy
 
+from nose.tools import with_setup, istest
+
 from flask import Flask
 
 # add more nose  tools
 
     return TestResponse
 
-_testing_ctx_stack = LocalStack()
-
-browser = LocalProxy(lambda: _testing_ctx_stack.top.browser)
-client = LocalProxy(lambda: _testing_ctx_stack.top.client)
-fixtures = LocalProxy(lambda: _testing_ctx_stack.top.fixtures)
-templates = LocalProxy(lambda: _testing_ctx_stack.top.templates)
-
-class _GlobalFixtures(object):
+class _Fixtures(object):
     pass
 
 class _TestContext(object):
 
         self.app = app
         
-        #self.client = APIClient()
-        #self.client.configure_in_scope()
-        
-        #self.browser = WebBrowser()
-        #self.browser.configure_in_scope()
-    
-        self.client = self.app.test_client()
-        self.fixtures = _GlobalFixtures()
-        self.templates = []
-
     def push(self):
 
-        _testing_ctx_stack.push(self)
+        self.ctx = self.app.test_request_context()
+        self.ctx.push()
+
+        self.client = self.app.test_client()
+        self.browser = None # will be Alfajor Web Browser
+        self.fixtures = _Fixtures()
+        self.templates = []
 
     def pop(self):
 
-        _testing_ctx_stack.pop()
+        self.fixtures = None
+        self.client = None
+        self.browser = None
         
+        self.ctx.pop()
+
     def __enter__(self):
         self.push()
         return self
             if app is None:
                 raise RuntimeError, "No app instance passed"
 
-            _app_ctx = app.test_request_context()
-            _app_ctx.push()
+            _test_ctx = _TestContext(app)
+            
+            def _setup():
+                _test_ctx.push()
 
-            _test_ctx = _TestContext(app)
-            _test_ctx.push()
+                if self._parent:
+                    for setup_func in self._parent._setup_funcs:
+                        setup_func(_test_ctx)
 
-            if self._parent:
-                for setup_func in self._parent._setup_funcs:
-                    setup_func()
-
-            for setup_func in self._setup_funcs:
-                setup_func()
+                for setup_func in self._setup_funcs:
+                    setup_func(_test_ctx)
 
             # template_rendered.connect(_add_templates)
 
-            try:
-                return func()
-                
-            finally:
-                
-                # template_rendered.disconnect(_add_templates)
+            def _teardown():
 
                 for teardown_func in self._teardown_funcs:
-                    teardown_func()
+                    teardown_func(_test_ctx)
 
                 if self._parent:
                     for teardown_func in self._parent._teardown_funcs:
-                        teardown_func()
+                        teardown_func(_test_ctx)
 
                 _test_ctx.pop()
-                _app_ctx.pop()
+            
+            try:
+                _setup()
+                return func(_test_ctx)
+            finally:
+                _teardown()
                 
         return decorate
 
     uses decorators::
 
         @testing.with_context
-        def test_index_page():
+        def test_index_page(ctx):
         
-            response = client.get("/")
+            response = ctx.client.get("/")
             testing.assert_202(response)
 
     or::
         
         @testing.setup
-        def create_db():
+        def create_db(ctx):
             db.create_all()
 
         @testing.teardown
-        def drop_db():
+        def drop_db(ctx):
             db.drop_all()
             db.session.remove()
 
         @testing.with_context
-        def test_index_page():
+        def test_index_page(ctx):
 
-            browser.open("/")
-            assert browser.status_code == 200
-            assert browser.document['#A'].tag == 'dl'
+            ctx.browser.open("/")
+            assert ctx.browser.status_code == 200
+            assert ctx.browser.document['#A'].tag == 'dl'
             
+    The "ctx" ("test context") argument is required for all test functions using
+    the @with_context, @setup and @teardown decorators.
+
+    It has the following properties:
+
+    - app: the current app
+    - fixtures: an empty data object, like Flask g, to append fixtures data to
+    - templates: list of template/contexts
+    - client - app client 
+    - browser - WebBrowser (TBD)
+
 
     """
     def __init__(self, app=None):

File tests/__init__.py

     jsonify, render_template, current_app
 
 from flaskext.testing import TestCase, TwillTestCase, \
-    ContextVariableDoesNotExist, Testing, client, fixtures, assert_404
+    ContextVariableDoesNotExist, Testing, assert_404
 
 def create_app():
 
 testing = Testing(create_app())
 
 @testing.with_context
-def test_is_current_app():
+def test_is_current_app(ctx):
     assert current_app
 
 @testing.with_context
-def test_index():
-    response = client.get("/")
+def test_index(ctx):
+    response = ctx.client.get("/")
     assert response.status_code == 200
 
 @testing.with_context
-def test_assert_something():
-    response = client.get("/foo/")
+def test_assert_something(ctx):
+    response = ctx.client.get("/foo/")
     assert_404(response)
 
 @testing.setup
-def set_x():
-    fixtures.x = 10
+def set_x(ctx):
+    ctx.fixtures.x = 10
 
 @testing.with_context
-def test_fixtures():
-    assert fixtures.x == 10
+def test_fixtures(ctx):
+    assert ctx.fixtures.x == 10
 
 testmod = testing.register_module()
 
 @testmod.setup
-def set_y():
-    fixtures.y = 20
+def set_y(ctx):
+    ctx.fixtures.y = 20
+
 
 @testmod.with_context
-def test_mod_fixtures():
-    assert fixtures.x == 10
-    assert fixtures.y == 20
+def test_mod_fixtures(ctx):
+    assert ctx.fixtures.x == 10
+    assert ctx.fixtures.y == 20
+
+def test_make_fail():
+    @testmod.with_context
+    def do_fail(ctx):
+        assert False, "BOO!"
+
+    try:
+        do_fail()
+        assert False
+    except AssertionError:
+        pass
 
 testmod2 = testing.register_module()
 
 @testmod2.setup
-def set_z():
-    fixtures.z = 30
+def set_z(ctx):
+    ctx.fixtures.z = 30
 
 @testmod2.with_context
-def test_mod2_fixtures():
-    assert fixtures.x == 10
-    assert fixtures.z == 30
+def test_mod2_fixtures(ctx):
+    assert ctx.fixtures.x == 10
+    assert ctx.fixtures.z == 30
     
     try:
-        fixtures.y == 20
+        ctx.fixtures.y == 20
         assert False, "y should not be here"
     except AttributeError:
         pass
 increments = testing.register_module()
 
 @increments.setup
-def increment():
+def increment(ctx):
     global value
     value += 1
 
 @increments.teardown
-def decrement():
+def decrement(ctx):
     global value
     value -= 2
 
 @increments.with_context
-def test_is_higher():
+def test_is_higher(ctx):
 
     print value, "higher?"
     assert value == 6
 
 @increments.with_context
-def test_is_lower():
+def test_is_lower(ctx):
     
     print value, "lower?"
     assert value == 5