I have a decorator that looks like so:
def validate_something(func):
def validate_s(request):
if request.property:
render_to_response('template.jinja', 'error'
return func(request)
return validate_something
I'm trying to test it like so. I load the local WSGI stack as an app.
from webtest import TestApp
def setUp(self):
self.app = TestApp(target_app())
self.config = testing.setUp(request=testing.DummyRequest)
def test_something(self):
def test_func(request):
return 1
request = testing.DummyRequest()
resp = validate_something(test_func(request))
result = resp(request)
The error I'm getting is (being generated at the innermost render_to_response):
ValueError: no such renderer factory .jinja
I understand that I need to mock render_to_response, but I'm at a bit of a loss as to how to exactly do that. If anyone has any suggestions, I would greatly appreciate it.
Mock library is awesome:
mock provides a core Mock class removing the need to create a host of
stubs throughout your test suite. After performing an action, you can
make assertions about which methods / attributes were used and
arguments they were called with. You can also specify return values
and set needed attributes in the normal way.
Additionally, mock provides a patch() decorator that handles patching
module and class level attributes within the scope of a test
Youc code would look like this:
def test_something(self):
test_func = Mock.MagicMock(return_value=1) # replaced stub function with a mock
request = testing.DummyRequest()
# patching a Pyramid method with a mock
with mock.patch('pyramid.renderers.render_to_response' as r2r:
resp = validate_something(test_func(request))
result = resp(request)
assert r2r.assert_called_with('template.jinja', 'error')
The following worked for me:
def setUp(self):
self.app = TestApp(target_app())
self.config = testing.setUp(request=testing.DummyRequest)
self.config.include('pyramid_jinja2')
By setting up the config to include jinja your tests can then find your template and the jinja environment. You may also need to provide a test version of the template in the same folder as your tests. If you get a message such as TemplateNotFound on running the tests then make sure a version of the template is located in the correct place.
Related
I have a question regarding unittest with Python! Let's say that I have a docker container set up that handles a specific api endpoint (let's say users, ex: my_site/users/etc/etc/etc). There are quite a few different layers that are broken up and handled for this container. Classes that handle the actual call and response, logic layer, data layer. I am wanting to write tests around the specific calls (just checking for status codes).
There are a lot of different classes that act as Handlers for the given endpoints. There are a few things that I would have to set up differently per one, however, each one inherits from Application and uses some methods from it. I am wanting to do a setUp class for my unittest so I don't have to re-establish this each time. Any advice will help. So far I've mainly seen that inheritance is a bad idea with testing, however, I am only wanting to use this for setUp. Here's an example:
class SetUpClass(unittest.TestCase):
def setUp(self):
self._some_data = data_set.FirstOne()
self._another_data_set = data_set.SecondOne()
def get_app(self):
config = Config()
return Application(config,
first_one=self._some_data,
second_one=self._another_data_set)
class TestFirstHandler(SetUpClass, unittest.TestCase):
def setUp(self):
new_var = something
def tearDown(self):
pass
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users')
self.assertEqual(res.code, 200)
class TestSecondHandler(SetUpClass, unittest.TestCase):
def setUp(self):
different_var_thats_specific_to_this_handler = something_else
def tearDown(self):
pass
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users/account/?something_custom={}'.format('WOW'))
self.assertEqual(res.code, 200)
Thanks again!!
As mentioned in the comments, you just need to learn how to use super(). You also don't need to repeat TestCase in the list of base classes.
Here's the simple version for Python 3:
class TestFirstHandler(SetUpClass):
def setUp(self):
super().setUp()
new_var = something
def tearDown(self): # Easier to not declare this if it's empty.
super().tearDown()
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users')
self.assertEqual(res.code, 200)
Hello I want to test a view of django. Inside of the view I create two objects which I want to mock some of their methods. The test looks like this
#mock.patch('payments_system.views.FirstObject')
#mock.patch('payments_system.helper_functions.SecondObject')
def test_make_payment_view_with_success(self, MockFirstObject, MockSecondObject):
MockFirstObject.get_value.side_effect = get_value_side_effect //this function is defined and implemented outside my testcase class
MockSecondObject.is_valid.return_value = True
factory = RequestFactory()
request = factory.post(reverse('cardinal-term_url'), data=dict(PaRes="test_parese", MD=None))
self._add_session_to_request(request)
session_data = dict(amount=1000, Centinel_PIType="VISA", Card_Number="40000000000000001", ExpMonth=06,
ExpYear=2016, Cvv2='123')
request = self._add_session_data_to_request(request, **session_data)
response = term_url(request)
self.assertRedirects(response, reverse('payments_system-success', kwargs={"token": "some_token"}))
When I debug my testcase and step in to my view, it is true that the objects created inside the view are of type of the Mocks. But the get_value method doesn't use the side_effect function but returns a MockingObject also. How can I pass the change in the mocking objects in the django view? Is the patch version the same as the following?
MockFirstObject = MagicMock(spec=payments_system.views.FirstObject)
MockSecondObject = MagicMock(spec=payments_system.helper_functions.SecondOjbect)
Do I need to do something more?
I finnaly managed to solve my issue. What I did was the following:
in the test function
mock_object1_instance = MockFirstObject1.return_value
mock_object1_instance.get_value.side_effect = get_value_side_effect
the same I did for the other mock object.
I've got a Flask application which I'd like to run some unit tests on. To do so, I create a new Flask object, initialise blueprints, SQLA and a few other packages and execute the test case.
However, I've noticed that some endpoints on the test flask object are missing, which made me wonder about the general way of how initialisation is handled in flask.
Taking a minimal example, an endpoint would be created like so:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
If I was to create a new Flask object somewhere in my testcase's setUp method, it would most certainly not contain a route '/' as this route was created from another flask object (the one from the file above). So my question is: How should a test case be written and how is the initialisation meant to work in general? Somewhere I read that one should avoid initialisation at import (i.e. on a module level), but this seems to be impossible if annotations are used.
You don't create a new Flask object in your test cases. You import your existing app instead.
In many project setups you already added all your extensions to that app. In many of mine I have a factory method that'll take a configuration object and returns the fully initialized app object for me; I use this to create a base test case:
import unittest
import project
class Config(object):
DEBUG = False
TESTING = True
CACHE_NO_NULL_WARNING = True # silence Flask-Cache warning
SECRET_KEY = 'SECRET_KEY'
class ProjectCoreViewCase(unittest.TestCase):
"""Base test case for the Project core app"""
def setUp(self, **kwargs):
config = Config()
config.__dict__.update(kwargs)
app = project.create_app(config)
self.app = app.test_client()
and any tests can then use self.app as the test client in all tests.
This is a base test case, you'd inherit from it; the setUp() method allows for additional configuration to be set, by passing in keyword arguments to a super() call:
class ConcreteTestCase(ProjectCoreViewCase):
def setUp(self):
super(ConcreteTestCase, self).setUp(
SQLALCHEMY_DATABASE_URI='your_test_specific_connection_uri',
)
I'm using Django 1.3 and need to check the output and number of interactions in my logging system. For logging I'm using Django-Sentry though it appears that it's working just like the regular Python logger.
I'm using python-mockito for mocking and if possible I would like to check the number of times different methods have been called and the messages they return.
I'm trying to achieve a check that does something like:
from foo import views
logger = mock()
views.logger = logger
do_method()
verify(logger).error(any, any)
do_method()
verifyZeroInteractions(logger)
Also being able to check the parameters would be nice.
models.py:
from django.db import models
import logging
from sentry.client.handlers import SentryHandler
logger = logging.getLogger(__name__)
try:
is_logging_setup = True
except NameError:
is_logging_setup = True
logger.setLevel(settings.LOGGING_LEVEL)
logger.addHandler(SentryHandler())
class Foo(models.Model):
def bar(self):
logger.warning("Rawr", 'extra': { 'data': 'foo' })
tests.py:
class TestModelFoo(TestCase):
def setUp(self):
self.foo = Foo()
def test_getting_logged(self):
self.foo.bar()
# Check the log output.
Any suggestions on how I can catch the output?
Here's some code that does just that with the standard mock python library.
with mock.patch('infra.manifest.fake_put') as fake_patch:
infra.manifest.copy_files(root, files, folder, True)
args, kwargs = fake_patch.call_args
self.assertEqual((u'/etc/a.tmp', u'/tmp/a.tmp'), args)
self.assertEqual({'use_sudo': True}, kwargs)
It's the mock.patch method you're interested in. I think there are other frameworks where you can specify a passthrough keyword which will also call the original method, this one will turn the patched method into a mock call and not call the original method.
I want to achieve maximum testability in my Google App Engine app which I'm writing in Python.
Basically what I'm doing is creating an all-purpose base handler which inherits the google.appengine.ext.webapp.RequestHandler. My base handler will expose common functionality in my app such as repository functions, a session object and the like.
When the WSGIApplication receives a request it will find the handler class that has been registered for the requested URL, and call its constructor and after that it will call a method called initialize passing in the request and response objects.
Now, for the sake of testability I want to be able to "mock" these objects (along with my own objects). So my question is how do I go about injecting these mocks? I can override the initialize method in my base handler and check for some global "test flag" and initialize some dummy request and response objects. But it seems wrong (in my mind at least). And how do I go about initializing my other objects (which may depend on the request and response objects)?
As you can probably tell I'm a little new to Python so any recommendations would be most welcome.
EDIT:
It has been pointed out to me that this question was a little hard to answer without some code, so here goes:
from google.appengine.ext import webapp
from ..utils import gmemsess
from .. import errors
_user_id_name = 'userid'
class Handler(webapp.RequestHandler):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
self.charset = 'utf8'
self._session = None
def _getsession(self):
if not self._session:
self._session = gmemsess.Session(self)
return self._session
def _get_is_logged_in(self):
return self.session.has_key(_user_id_name)
def _get_user_id(self):
if not self.is_logged_in:
raise errors.UserNotLoggedInError()
return self.session[_user_id_name]
session = property(_getsession)
is_logged_in = property(_get_is_logged_in)
user_id = property(_get_user_id)
As you can see, no dependency injection is going on here at all. The session object is created by calling gmemsess.Session(self). The Session class expects a class which has a request object on it (it uses this to read a cookie value). In this case, self does have such a property since it inherits from webapp.RequestHandler. It also only has the object on it because after calling (the empty) constructor, WSGIApplication calls a method called initialize which sets this object (and the response object). The initialize method is declared on the base class (webapp.RequestHandler).
It looks like this:
def initialize(self, request, response):
"""Initializes this request handler with the given Request and
Response."""
self.request = request
self.response = response
When a request is made, the WSGIApplication class does the following:
def __call__(self, environ, start_response):
"""Called by WSGI when a request comes in."""
request = self.REQUEST_CLASS(environ)
response = self.RESPONSE_CLASS()
WSGIApplication.active_instance = self
handler = None
groups = ()
for regexp, handler_class in self._url_mapping:
match = regexp.match(request.path)
if match:
handler = handler_class()
handler.initialize(request, response)
groups = match.groups()
break
self.current_request_args = groups
if handler:
try:
method = environ['REQUEST_METHOD']
if method == 'GET':
handler.get(*groups)
elif method == 'POST':
handler.post(*groups)
'''SNIP'''
The lines of interest are those that say:
handler = handler_class()
handler.initialize(request, response)
As you can see, it calls the empty constructor on my handler class. And this is a problem for me, because what I think I would like to do is to inject, at runtime, the type of my session object, such that my class would look like this instead (fragment showed):
def __init__(self, session_type):
'''
Constructor
'''
self.charset = 'utf8'
self._session = None
self._session_type = session_type
def _getsession(self):
if not self._session:
self._session = self._session_type(self)
return self._session
However I can't get my head around how I would achieve this, since the WSGIApplication only calls the empty constructor. I guess I could register the session_type in some global variable, but that does not really follow the philosophy of dependency injection (as I understand it), but as stated I'm new to Python, so maybe I'm just thinking about it the wrong way. In any event I would rather pass in a session object instead of it's type, but this looks kind of impossible here.
Any input is appreciated.
The simplest way to achieve what you want would be to create a module-level variable containing the class of the session to create:
# myhandler.py
session_class = gmemsess.Session
class Handler(webapp.Request
def _getsession(self):
if not self._session:
self._session = session_class(self)
return self._session
then, wherever it is that you decide between testing and running:
import myhandler
if testing:
myhandler.session_class = MyTestingSession
This leaves your handler class nearly untouched, leaves the WSGIApplication completely untouched, and gives you the flexibility to do your testing as you want.
Why not just test your handlers in isolation? That is, create your mock Request and Response objects, instantiate the handler you want to test, and call handler.initialize(request, response) with your mocks. There's no need for dependency injection here.