I'm following along with a lecture on django testing and this is one of the tests:
def test_invalid_flight_page(self):
max_id = Flight.objects.all().aggregate(Max("id"))["id__max"]
c = Client()
response = c.get(f"/flights/{max_id + 1}")
self.assertEqual(response.status_code, 404)
When I run manage.py tests it throws an error on this test, essentially saying there is no matching flight:
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.......E..
======================================================================
ERROR: test_invalid_flight_page (flights.tests.FlightTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\sarah\Desktop\airline\flights\tests.py", line 68, in test_invalid_flight_page
response = c.get(f"/flights/{max_id + 1}")
File "C:\Python\Python385\lib\site-packages\django\test\client.py", line 732, in get
response = super().get(path, data=data, secure=secure, **extra)
File "C:\Python\Python385\lib\site-packages\django\test\client.py", line 393, in get
return self.generic('GET', path, secure=secure, **{
File "C:\Python\Python385\lib\site-packages\django\test\client.py", line 470, in generic
return self.request(**r)
File "C:\Python\Python385\lib\site-packages\django\test\client.py", line 709, in request
self.check_exception(response)
File "C:\Python\Python385\lib\site-packages\django\test\client.py", line 571, in check_exception
raise exc_value
File "C:\Python\Python385\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Python\Python385\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\sarah\Desktop\airline\flights\views.py", line 21, in flight
flight = Flight.objects.get(pk=flight_id)
File "C:\Python\Python385\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python\Python385\lib\site-packages\django\db\models\query.py", line 429, in get
raise self.model.DoesNotExist(
flights.models.Flight.DoesNotExist: Flight matching query does not exist.
----------------------------------------------------------------------
Ran 10 tests in 0.120s
FAILED (errors=1)
Destroying test database for alias 'default'...
But that is the point, there is no flight with that id so the response status code for that request should equal 404. As far as I can see I have copied the code accurately from the lecture but the lecturer's tests are all running okay. Can anyone see what I may be missing?
When I change the expected response.status_code to 200 self.assertEqual(response.status_code, 200) it gives me the same error so this indicates to me that the main problem lies with the response line?
Please let me know if there is anything more you need to see.
Your view class is not handling when the query resolves to nothing. In django it's done as follows:
try:
result = SomeModel.objects.get(pk=some_id)
except SomeModel.DoesNotExist:
# Return 404 here
I've met the same problem. Indeed, it came from the response line or client.get() method itself. In my case, I add "/" at the end of the quotation mark as:
response = c.get(f"/flights/{max_id + 1}/")
And then check assert condition. Now it functions as I want.
Also found that:
If you substitute a word instead of a number as an invalid page, it works just fine. For example:
THIS ONE OK (404 were detected):
response = c.get(f"/flights/whatever")
THIS ONE DOESN'T WORK (404 were not detected and errors were alerted):
response = c.get(f"flights/15")
Related
I was working on my project and everthing worked fine. I tried to open the server in another browser and this error appeared. I stopped the project and start it agian and it stop working on my main browser aswell. I dont have any idea what this cause it.
Internal Server Error: /account/login/
Traceback (most recent call last):
File "A:\repos\topanime\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "A:\repos\topanime\venv\lib\site-packages\django\core\handlers\base.py", line 204, in _get_response
response = response.render()
File "A:\repos\topanime\venv\lib\site-packages\django\template\response.py", line 105, in render
self.content = self.rendered_content
File "A:\repos\topanime\venv\lib\site-packages\django\template\response.py", line 83, in rendered_content
return template.render(context, self._request)
File "A:\repos\topanime\venv\lib\site-packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
File "A:\repos\topanime\venv\lib\site-packages\django\template\base.py", line 168, in render
with context.bind_template(self):
File "C:\Python\Python391\lib\contextlib.py", line 117, in __enter__
return next(self.gen)
File "A:\repos\topanime\venv\lib\site-packages\django\template\context.py", line 244, in bind_template
updates.update(processor(self.request))
ValueError: dictionary update sequence element #0 has length 0; 2 is required
[18/Mar/2021 18:52:01] "GET /account/login/ HTTP/1.1" 500 86400
If there is any other information that you need tell me.
The problem was that I had a view in context_processors that required login #login_required. So I couldnt load any page because i wasnt logged in
If you use #login_required in context_processors:
The way I solved it was by replacing it with an if statment inside the context_processor.
def myCP(self, *args, **kwargs):
kontext = {}
if self.user.is_authenticated:
# The user is logged in
kontext['loggedIn'] = True
else:
# The user is logged out
kontext['loggedIn'] = False
return kontext
Trying to get the GET parameters from the URL. I have it working in my __init__.py file, but in a different file its not working.
I tried to use with app.app_context(): but I am still getting the same issue.
def log_entry(entity, type, entity_id, data, error):
with app.app_context():
zip_id = request.args.get('id')
RuntimeError: working outside of request context
Any suggestions?
Additional Info:
This is using Flask web framework which is setup as a service (API).
Example URL the user would hit http://website.com/api/endpoint?id=1
As mentioned above using `zip_id = request.args.get('id') works fine in the main file but I am in runners.py (just another file with definitions in)
Full traceback:
Debugging middleware caught exception in streamed response at a point where response headers were already sent.
Traceback (most recent call last):
File "/Users/ereeve/.virtualenvs/pi-automation-api/lib/python2.7/site-packages/werkzeug/wsgi.py", line 703, in __next__
return self._next()
File "/Users/ereeve/.virtualenvs/pi-automation-api/lib/python2.7/site-packages/werkzeug/wrappers.py", line 81, in _iter_encoded
for item in iterable:
File "/Users/ereeve/Documents/TechSol/pi-automation-api/automation_api/runners.py", line 341, in create_agencies
log_entry("test", "created", 1, "{'data':'hey'}", "")
File "/Users/ereeve/Documents/TechSol/pi-automation-api/automation_api/runners.py", line 315, in log_entry
zip_id = request.args.get('id')
File "/Users/ereeve/.virtualenvs/pi-automation-api/lib/python2.7/site-packages/werkzeug/local.py", line 343, in __getattr__
return getattr(self._get_current_object(), name)
File "/Users/ereeve/.virtualenvs/pi-automation-api/lib/python2.7/site-packages/werkzeug/local.py", line 302, in _get_current_object
return self.__local()
File "/Users/ereeve/.virtualenvs/pi-automation-api/lib/python2.7/site-packages/flask/globals.py", line 20, in _lookup_req_object
raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context
Def in the same file calling the log_entry def
def create_agencies(country_code, DB, session):
document = DB.find_one({'rb_account_id': RB_COUNTRIES_new[country_code]['rb_account_id']})
t2 = new_t2(session)
log_entry("test", "created", 1, "{'data':'hey'}", "")
I followed the Django doc to write tests with assertRaisesMessage() but the problem is the exception itself is raised when executing test (so, the test is not executed).
Note that the exception called is an exception I voluntarily raise in a method of my model (not in the view).
class MyTestCase(TestCase):
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
resp = self.client.get(reverse(invertRewardState, args=(1,)))
self.assertRaisesMessage(
expected_exception=Exception,
expected_message=EXC_NOT_YOURS,
callable_obj=resp)
How Should I use AssertRaisesMessage() to let my test be executed without raising the Exception?
Thanks.
EDIT :
After trying falsetru 1st solution, the problem is still the same. As soon as my test enters in the resp = ... part, view is called, then related model method is called and raises the exception.
the full stack trace :
Traceback (most recent call last):
File "/Users/walt/Code/hellodjango/clientizr/tests.py", line 338, in test_invertRewardState_view_fails_notmy_reward
resp = self.client.get(reverse(invertRewardState, args=('1',)))
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 473, in get
response = super(Client, self).get(path, data=data, **extra)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 280, in get
return self.request(**r)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 444, in request
six.reraise(*exc_info)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 22, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/Users/walt/Code/hellodjango/clientizr/views.py", line 234, in invertRewardState
reward.invert_reward_state(request.user)
File "/Users/walt/Code/hellodjango/clientizr/models.py", line 606, in invert_reward_state
self.throw_error_if_not_owner_reward(cur_user)
File "/Users/walt/Code/hellodjango/clientizr/models.py", line 587, in throw_error_if_not_owner_reward
raise Exception(EXC_NOT_YOURS)
Exception: Cet objet n'est pas le v\xf4tre
You use assertRaisesMessage as a context manager around the code you expect to fail:
class MyTestCase(TestCase):
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
url = reverse(invertRewardState, args=(1,))
with self.assertRaisesMessage(Exception, EXC_NOT_YOURS):
self.client.get(url)
If you use self.client.get, you will not get an exception directly, but you can check status code.
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
resp = self.client.get(reverse(invertRewardState, args=('1',)))
self.assertEqual(resp.status_code, 500)
self.assertIn(EXC_NOT_YOURS in resp.content)
If you want to get an exception, call the view directly.
def test_invertRewardState_view_fails_notmy_reward(self):
request = HttpRequest()
request.user = User.objects.create(email='gislaine#toto.com') # login
self.assertRaisesMessage(Exception, EXC_NOT_YOURS, invertRewardState, '1')
You can use context manager form as Ned Batchelder suggested.
I have written a unit test to test an api....Its a GET call....
When I run it , i get this error ...Heres the traceback....
Traceback (most recent call last):
File "/home/arindam31/XXX-Name/mapi/tests.py", line 141, in test_get_cities
response = self.cl.get('/mapi/latest/cities/')
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 445, in get
response = super(Client, self).get(path, data=data, **extra)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 229, in get
return self.request(**r)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 387, in request
response = self.handler(environ)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 84, in __call__
response = self.get_response(request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 169, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 218, in handle_uncaught_exception
return callback(request, **param_dict)
File "/home/arindam31/XXX-Name/saul/views.py", line 546, in do_handle_500
return render_to_response("500.html", context_instance=RequestContext(request))
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 177, in __init__
self.update(processor(request))
File "/home/arindam31/XXX-Name/saul/context_processors.py", line 46, in common_context
ret_dict['city'] = request.city
AttributeError: 'WSGIRequest' object has no attribute 'city'
Heres my unit test...
def test_get_cities(self):
request = HttpRequest()
request.city = self.c1
response = self.cl.get('/mapi/latest/cities/')
content = response.content
data = json.loads(content)
for city in City.objects.all():
assert city.name in data
assert data[city.name] == city.pk
Here , self.c1 is a city type object in the setUp part....HttpRequest is from django.http.
The view being tested is below:
def get_cities(request):
print "1"
if ENABLE_HTTPS_CHECK and not request.is_secure():
return HttpResponseForbidden()
if request.method != 'GET':
return HttpResponseNotAllowed('Not allowed')
city_map = _get_city_map()
response = HttpResponse(json.dumps(city_map)
content_type='application/json')
response['Cache-Control'] = 'no-cache'
return response
If you want to test your view with your own request object, you should call the view directly. You should use the RequestFactory to create your request.
As Daniel Roseman points out your request object having a city attribute remains broken, unless you have some middleware that would set it. You clearly have some middleware that require it to be set in saul/context_processors.py.
Using RequestFactory and calling the view directly circumvents the middleware entirely, so you can concentrate on testing your view (if the view supports the absent middleware).
If your view requires the middelware to be operational, you probably just need to be logged in using the test client. It has a session pr test method.
I have no idea what you are trying to do here. You instantiate a request object, assign a city attribute, then proceed to ignore that object and just use the standard test client. I don't know why you would think that that request would be used for the client get.
To be honest though I think that your entire design is broken. You don't show how you expect to get the parameter into the request in a normal non-test scenario, but usually you would pass it via the POST or GET parameters rather than annotating it into the request somehow. That would of course make it easier to test, since you could just pass the dictionary to the client call.
I'm using the #login_required decorator in my project since day one and it's working fine, but for some reason, I'm starting to get "
AttributeError: 'unicode' object has no attribute 'user' " on some specific urls (and those worked in the past).
Example : I am the website, logged, and then I click on link and I'm getting this error that usually is linked to the fact that there is no SessionMiddleware installed. But in my case, there is one since I am logged on the site and the page I am on also had a #login_required.
Any idea?
The url is definied as : (r'^accept/(?P<token>[a-zA-Z0-9_-]+)?$', 'accept'),
and the method as : #login_required
def accept(request,token): ...
The Traceback:
Traceback (most recent call last):
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/core/servers/basehttp.py", line 674, in __call__
return self.application(environ, start_response)
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/core/handlers/wsgi.py", line 241, in __call__
response = self.get_response(request)
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/core/handlers/base.py", line 141, in get_response
return self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/core/handlers/base.py", line 165, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/core/handlers/base.py", line 100, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/Users/macbook/dev/pycharm-projects/proj/match/views.py", line 33, in accept
return __process(token,callback)
File "/Users/macbook/virtualenv/proj/lib/python2.6/site-packages/django/contrib/auth/decorators.py", line 24, in _wrapped_view
if test_func(request.user):
AttributeError: 'unicode' object has no attribute 'user'`
The decorator was on a private method that doesn't have the request as a parameter. I removed that decorator (left there because of a refactoring and lack of test [bad me]).
Problem solved.
This can also happen if you call a decorated method from another method without providing a request parameter.