generate common tests for django - django

I'm developing sites on django I'm think what most problems may be found by using smoke coverage tests method. But (in most cases) write the tests to check response code is 200 for every app, every view, and every url is so bored (e.g. when you are develop few sites parallel). I have a question: How can I automate this process, may be exist some complete solutions to generate some common tests for django.
Thanks!

Best practices:
If it can break, it should be tested. This includes models, views,
forms, templates, validators, and so forth.
Each test should generally only test one function.
Keep it simple. You do not want to have to write tests on top of
other tests. Run tests whenever code is PULLed or PUSHed from the
repo and in the staging environment before PUSHing to production.
When upgrading to a newer version of Django:
-upgrade locally,
-run your test suite,
-fix bugs,
-PUSH to the repo and staging, and then
-test again in staging before shipping the code.
https://realpython.com/blog/python/testing-in-django-part-1-best-practices-and-examples/
Django provides a small set of tools that come in handy when writing tests.
The test client
The test client is a Python class that acts as a dummy Web browser, allowing you to test your views and interact with your Django-powered application programmatically.
Some of the things you can do with the test client are:
Simulate GET and POST requests on a URL and observe the response –
everything from low-level HTTP (result headers and status codes) to
page content.
See the chain of redirects (if any) and check the URL and status code
at each step.
Test that a given request is rendered by a given Django template,
with a template context that contains certain values.
Overview and a quick example
To use the test client, instantiate django.test.Client and retrieve Web pages:
from django.test import Client
c = Client()
response = c.post('/login/', {'username': 'john', 'password': 'smith'})
response.status_code
200
response = c.get('/customer/details/')
response.content
'<!DOCTYPE html...'
As this example suggests, you can instantiate Client from within a session of the Python interactive interpreter.
Testing responses
The get() and post() methods both return a Response object. This Response object is not the same as the HttpResponse object returned by Django views; the test response object has some additional data useful for test code to verify.
Making requests
Use the django.test.Client class to make requests.
class Client(enforce_csrf_checks=False, **defaults)
Exceptions
If you point the test client at a view that raises an exception, that exception will be visible in the test case. You can then use a standard try ... except block or assertRaises() to test for exceptions.
Provided test case classes
Normal Python unit test classes extend a base class of unittest.TestCase. Django provides a few extensions of this base class:
Hierarchy of Django unit testing classes (TestCase subclasses)
Hierarchy of Django unit testing classes
For detailed information and more examples visit https://docs.djangoproject.com/en/1.7/topics/testing/tools/

Related

Populating db data for django's built-in testing tools

I'm using Django(1.8) + DRF + uwsgi + nginx and trying to unit-test API that I've made. To run tests I need to populate db (create users, for example) and use this data in all tests. So I've tried two ways:
Create directly in TestCase.setUp:
class ApiTests(TestCase):
def setUp(self):
Account.objects.create_user(username='username', password='password')
Or use fixtures:
class ApiTests(TestCase):
fixtures = ['dump.json']
Next I run my project through supervisor:
system("service supervisord startall")
After everything is ready I try to access my API in test to login, using:
login_data = {"username": "username", "password": "password"}
rslt = client.post(HOST_NAME + '/login/', data=login_data)
... but I can't authorize, because users somehow don't exist in the db!
As I've found in the docs to Django tests, TestCase doesn't write data into db, but store it in a transaction, that is rolled back after testing. And as I can see I can get this data only on test-side (using User.objects.all() that is showing that users are created), but not on my nginx-server-side (User.objects.all() on this side shows 0 items).
ATM I can see few options:
Somehow force TestCase to commit data into db.
Populate data in other methods (but which?).
Use different testing libs.
Could you please help?
You shouldn't use web server to test django views even though in reality views do need to be driven by web servers. In order to test request/response behavior, you should use django test client. Django doc has excellent example about that, quoting:
>>> from django.test import Client
>>> c = Client()
>>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
>>> response.status_code
200
>>> response = c.get('/customer/details/')
>>> response.content
b'<!DOCTYPE html...'
On top of that, the doc explains in details how to do GET, POST request and how to test view's response, etc. Hope that makes sense.
Yes! You've already identified the problem. Django TestCase executes in its own little insulated environment. It will create test database prefixed with test_ at the beginning of each suite run, and will execute each test in a transaction, so even if you start the the test suite, pause it after initialization, set the django config that supervisord points to to the test database, continue test execution you will still not see any data.
The reason you will not see any data in the example above is because the test has its own transaction, then when you make a request to your webserver, the webserver will open up a different transaction and will not be able to see the uncommitted data from your test.
To test your views (in my experiences) django TestCases and test clients, usually get you 95% there. They are very fast because each test is executed in a transaction, they expose a test client, that mimics a request (url routing, middleware, view loading, template processing, etc).
Using TestCase should faithfully test all your logic and database interactions, but it still leaves a gap of if supervisor, nginx, uwsgi, django app are functioning correctly. When you have extensive coverage using TestCase simple integration/smoke tests should suffice to verify the services above can communicate correctly. Ie bring up the stack, hit a status page that will test -> Supervisor -> Nginx -> uwsgi -> django -> DB -> back out.
There are def a lot of options for purely functional tests, but why test at a flaky , timely to maintain level when django provides you the tools to verify your application in a reliable, quick, easy to use manner?
If you need a server to be available to a browser for a browser based test, django provides LiveServerTestCase
If you need to write extensive functional tests I have found great success in exposing fixutre creation methods as API methods. This way your tests would be executed AGAINST a stack, an arbitrary stack, in this case it will be against a test stack you bring up locally, but since the tests are separate they could be executed against a QA or staging or even prod stack.

How to perform integration test of a backbone app

I want to perform integration testing i.e. automated testing for my backbone app using Selenium and Mocha but the problem I am encountering is that the selenium's webdriver looks for the html elements in the source code of the page, but in my app I am rendering the page using the views so there is no information of the elements in the source code of the particular page.
Like this: driver.findElement(webdriver.By.id('password')).sendKeys("password");
Consider the login functionality: I have two text fields, username and password with the same id, webdriver tries to look for these elements through the id in the source code but that is not present, and hence my test fails citing "No such element".
How should I move forward in order to perform integration test for my app?

Recommended way of talking to a Django application URL, from within a view of the same application?

I have a Django application, and need to deal with the following:
One of my views, needs to make a POST request to another URL endpoint of the same application.
In order to do so, I use the requests module. I assemble the URL of the endpoint I need to call, dump the POST parameters, and perform the call.
This works fine for the most part, however fails miserably when testing, since the view that corresponds to the URL that I talk to, knows nothing about the state of the testing environment.
The code is similar to this:
from django.conf import settings
import json
def view1(request, *args, **kwargs):
url = 'http://api.%s/view2/' % settings.DOMAIN
r = requests.post(
url,
data=json.dumps({'key': 'value'}),
)
// Notice that the ``url`` is a url of the actual deployed application,
// and therefore knows nothing about testing and its state. That's where
// it goes wrong.
The question is, is there a way that this can behave correctly in testing? I use the django.test.client.Client class for creating my test requests. As far as I know, instances of this class talk directly to the URL mapper. Therefore the url that I construct in the view is simply an external http request to the deployed application, instead of the tested application.
Thanks.
One way to solve this is to mock the response from the URL for the purposes of the tests. I'd suggest using a lightweight mocking library, such as this:
http://blog.moertel.com/posts/2011-11-07-a-flyweight-mocking-helper-for-python.html
See the example code. It's very similar to your situation. I've used both of these in combination with requests and flask, but not django.

testing securityConfig mapping in grails + acegi

I'm writing test cases for a project which still uses the Acegi plugin (not the newer Spring Core Security plugin) and as of now, I've managed to do what this site (http://www.zorched.net/2008/09/01/grails-testing-acegi-security/)
has suggested regarding the detection of which user is currently logged in. However, in my controller, I have stuff that looks like this:
def list = {
// code for an "admin account"
}
def list_others = {
// code for other accounts
}
Now, I do not check in the controller the logged in user. Instead, I have these defined in the SecurityConfig.groovy like:
security {
...
requestMapString = """\
/someController/list=ROLE_ADMIN
/someController/list_others=ROLE_OTHERS
"""
...
}
Hence, if I had a test that looked like this:
void testTrial() {
// define here that otherUser has a role of ROLE_OTHERS
authenticate(otherUser, "other") // this calls the authenticate methode in the site I gave earlier
controller.list()
// I do an assertion here to check where this goes to
}
Thing is, when I do the assertion, of course list will tell me that it forwarded to list.gsp... even if the "logged in" user has a role of ROLE_OTHERS and not an admin.
However, what I need is how to test what a logged-in user is only supposed to access? In this case, given that the call is to *.list() and the logged in user has a ROLE_OTHERS role, I should have been forwarded to a "denied" page.
Help? Thanks!
You'll need functional tests for this. Unit tests are just Groovy or Java classes plus some mocking. There's no Spring application context, no Hibernate, no database, and most importantly for this case no plugins.
Integration tests give you more functionality, but even there requests are mostly simulated and since there's no container, no filters fire. Spring Security (which the Acegi plugin uses) is based on a chain of servlet filters. So if you want to test that your security rules are being applied correctly you'll need a running server, hence functional tests.
There are several options for functional testing, the most popular ones being WebTest: http://grails.org/plugin/webtest, the Functional Testing plugin: http://grails.org/plugin/functional-test, and the Selenium RC plugin: http://grails.org/plugin/selenium-rc.
The newest one is Geb: http://grails.org/plugin/geb. The manual is at http://geb.codehaus.org/ and there was a recent blog post written about it here: http://blog.springsource.com/2010/08/28/the-future-of-functional-web-testing/

How to simulate a HTTP Post request from a django view without a template

I am writing views, not so keen to write templates right away.
But I need to test my program by submitting post requests.
How do i simulate HTTP Post from within a django view
I am aware that urllib2 and httplib modules of python allow a lot of options, but I am looking for something that elegantly integrates into the django views.
Would U create a method that performs post, where would you call it from?
Update: Some of the answers deal with testing by sending a POST to my application. What if I want to POST to an external service and deal with POST response. How can I do it without writing templates.
Django has a built in mock Client utility that can mimic requests as if they are coming from a browser. If you don't need to fully mimic a browser and just want to invoke your views directly from your tests, consider using a RequestFactory instead.
For such cases I think RequestFactory is ideally suited.
It works just like django's test client with the difference that it let's you create a request object that you can use anywhere. So you could just create your own request object and pass it to your view or form for testing.
I like this method of testing more then using the test client, since it comes closer to pure unit testing. That is, testing a single piece of code. If you're using the test client, there are more layers added before the actual code you're testing is reached.
To avoid the pain of creating the request object yourself you can use this tip on Django snippets
It sounds like you are looking for either a unit test or an acceptance test. Take a look at unittest which is part of the standard library.
For quick ad hoc tests while developing web apps, I like to use curl. It's a simple command line tool that easily generates all sorts of HTTP requests. You can POST with a command like:
curl -i -d field=value http://localhost:8080/sample/something
Curl is available on a lot of platforms. Check it out at http://curl.haxx.se/
If you are looking at this from the context of writing unittests, you could consider creating the Request object yourself and just calling the view function directly. You could even mock it, and any other parameters the view might take.