Best practices for getting the most testing coverage with Django/Python? - python

My tests are seriously lacking and I don't have a whole lot of faith in them. What are some of the best practices for getting the most testing coverage I can using Django/Python? I've been taking a look at Freshen and Lettuce, which look pretty promising, but I can't use them for everything, can I? I'm looking for advice on how to structure my workflow/project with testing so that I can feel confident when deploying new code in a production environment.

Stop coding.
Write the tests for the things your application is supposed to do.
First, use the built-in Django testing. Write model tests as TestCase classes inside your models.py.
Do that now. Before reading any further. Add django.test.TestCase classes right now that create, modify and retrieve model objects. Be sure you have a test method for each property, attribute, or extra method you defined.
I'll wait until you've finished that.
Model tests complete? Good.
Now create a tests.py file in each application. Every single one. All empty.
In each tests.py file create django.test.TestCase classes for each Form.
Do it now. Create good and bad forms. Create forms with each individual field validation problem.
Don't create all possible permutations of bad data. Just one test case for each individual validation rule.
Do that now. Before reading any further. Add django.test.TestCase classes to tests.py for each Form.
I'll wait until you've finished that.
Now, you have to test each view function. They also go in the tests.py file. Each view function has at least two test cases, perhaps more, depending on the various decorators you're using.
If a view function requires a login, you have two cases: logged in and not logged in.
If a view function requires a permission, you have at least three cases: not logged in, logged in as the wrong user, logged in as the right user.
For now, you just need to be sure that the view function did something and returns the correct HTML template with any piece of correct data. Don't go crazy. You just want to be sure all view functions actually return an expected page. Nothing more.
Do that now. Before reading any further. Add django.test.TestCase classes to tests.py for each view function.
I'll wait until you've finished that.
Those are the tests you should write first before writing any application code.
This will give you a testing baseline that confirms that your application will minimall sort-of run.
One you have that finished, you can start to consider unit tests that reflect the real purpose and value behind your application.

Additionally this series of articles so far has some good advice on testing django apps:
http://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/
My only criticism of the answer would be to not store everything in the tests.py file, but do as the article suggest. Create a tests directory and turn it in to a module by adding an __init__.py file and importing all your test cases there. eg from myapp.tests.views import *. But definitely sound advice. Gotta walk before you can run… tests! See what I did there?

I'm assuming that you are done with Testing Django Applications. With the right set of helper tools you should be fine with the default unit testing using Django test framework.
To get you started with measuring coverage you might want to look into coverage standalone to figure out what you have tested.
Once installed, you can do something like this:
$ coverage run manage.py test *yourapp*
It will create .coverage file for you. You can format the data from this file with
$ coverage report
to get a full list on testing coverage (including code from other python libraries).
You can easily coverage report --omit path modules that start with particular paths. Additionally you would be able to see the lines that were not executed during the test run with -m option.
Also, I think there is a django_coverage Django application that integrates coverage into testing for Django project. It makes nice HTML coverage reports for you.
Now there are other tools like twill, etc. to address specific needs (like javascript testing).
Also, if you want to go through the detailed baby steps of setting up vanilla testing under Django, you may want to read "Django 1.1 Testing and Debugging" (lookup on Amazon).

Related

Django - How to port scripts to django

Before I ask my question I need to give some context:
I wrote a simple python script that read linux's syslog file and search for certain strings. I have other similar scripts like these (scripts that do file system stuff, scripts that interact with other servers and so on). Most of these scripts write simple write stuff to stdout.
I would like to port these scripts to a web-server so I could simple browser to https://server/syslog and get the same output that I would get by running the script on the command line interface.
According with my research Django seems to be a great choice. I followed some Django tutorials and I was capable of developing some basic django web apps.
My question is: Since django does not have a "controller" where should I place the scripts code? My best bet in the view, but according with djangos documentation it does not make sence.
Extracted from django doc: In our interpretation of MVC, the “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it. It’s a subtle distinction.
The description of MVC is not so important. The typical use of django is for database backed web applications. And this describes a design pattern or paradigm for that. It's completely possible to use django in other ways as well.
If you want to build a django app that is a web interface for your existing scripts, you might not even need the django ORM at all. In any case, you can put as much or as little logic in your view as you want. Your use case might just not fit neatly into the MVC or MVT paradigm. Django views are just python functions (or classes, but Django class based views are more tightly coupled with the ORM).
I would recommend:
leaving your scripts largely as they are, but wrap the parts you want to reuse as
functions. You can keep them functional as standalone scripts with an
if __name__=='__main__':
block to call the functions.
Import the functions to views.py - it doesn't matter where they are as long as your server will always be able to find them. I put mine right in the app directory.
Call the function(s) in your view(s), and return the text to a HttpResponse object which you return from the view. (I think this is more direct than creating a template and a context and calling render, but its not what I usually do so there may be some issues?)
Thats bit old code - but you will get enough idea to start - check https://github.com/alex2/django_logtail (Django_LogTail)

Writing test cases for sqlalchemy models in pyramid

I'm building an application with pyramid and sqlalchemy. I'm trying to work as clean as possible, so right now I'm just writing models and try to do solid test cases for them. Ideally I'd expect them to accept a database configuration to work with (since different DB systems do differ; for the application I'll be working with mysql), but even a decent way of doing it with sqlite would help.
The page Adding Tests in the SQLAlchemy + URL Dispatch Wiki Tutorial somehow is not too helpful on that part, as it says
To test the model class Page we'll add a new PageModelTests class to our tests.py file that was generated as part of the alchemy scaffold.
but then it fails to mention said PageModelTests class ever again.
Does anyone know a helpful tutorial on that?
I just presented on testing SQLAlchemy models in Pyramid in my talk Building the App. Two approaches are presented, the "transactional" and the "mock" style. For a demonstration of these methods as well as a comparison of techniques, see the example app at https://bitbucket.org/zzzeek/pycon2014_atmcraft/:
fixtures
transactional testing examples
mock testing examples

What is a good Django workflow?

I'm a beginner to Python and Django.
When starting a new project what do you do first before diving into the code?
For example, one could take the following steps:
Configure the settings.py file first
Configure models.py to lay out data structure
Create template files
Define the views/pages
Syncdb
etc
So my question is, what is a good workflow to get through the required steps for a Django application? This also serves as a checklist of things to do. In the definitive guide to Django, the author talks about approaching top down or bottom up. Can anyone expand further on this and perhaps share their process?
Thanks.
Follow the Agile approach. Finish one small case, from the start to the end. From the models to the tests to user experience. Then build on it. Iterate.
Thats the right way to software development.
To do it efficiently, you need: (don't bother right away, you will need it.)
Automated schema migration, automated build system, auto updating and deployment. - None of these, django has got anything to do with. Use pip, fabric, hudson, twill and south appropriately.
Take care not to over burden yourself with all these right away, particularly since you say, you are beginning.
the required steps for a Django application?
There are two required steps.
Write the settings. Write the urls.py
The rest of the steps are optional.
This also serves as a checklist of things to do.
Bad policy. You don't need a checklist of Django features. You need a collection of use cases or user stories which you must implement.
For some reason, you've omitted the two most important and valuable features of Django. Configure the default admin interface and write unit tests. The default admin interface is very high value. Unit testing is absolutely central.
You do it like this.
Gather use cases.
Prioritize the use cases.
Define the actors. The classes of actors becomes groups in the security model.
Define enough "applications" to satisfy the first release of use cases. Define the url structure. Cool URL's don't change.
Build the first use case: models (including security), admin, urls, tests, forms, views and templates. Note that these are the file names (models.py, admin.py, ...) except for templates. Also note that forms and admin should be defined in separate modules even though this isn't required. Also note that templates will be split between a generic templates directory for top-level stuff and application-specific templates.
Build the second use case: models (including security), admin, urls, tests, forms, views and templates.
...
n. Package for release. Tweak up the settings. Configure database and mod-wsgi
I personally can't make a template without writing the views (unless it's a photoshop draft) but in general that's the way I go after I have a plan.
What's extremely important for me is that I don't dive head-first into the code, and that I spend time mocking up the model structure based on the "screens" or "pages" that the user will see.
Once I have a user experience defined, I make sure the backend is robust enough to handle that experience. If I don't visualize the user experience, details get left out that are certainly accomplishable in the shell but not ideal for the website, default django admin, etc.
There are always tradeoffs between agile development and a huge spec: I think there's an important balance. Agile is good: there's no point planning every detail before writing your first line of code, as your needs will change by the time you get to the end. You don't know how your users will really use the site.
On the other hand, without a plan, you can end up with a messy foundation that affects all future code.
An educated guess is a good start. Don't think or assume too much, but definitely have a clear idea how your users will interact with your site for stage 1.
Always try to remember about a DRY rule. For example, why to write RequestContext every new view is defined, where you can simply write a function once, which will add it for you. Good description is here in another topic.
Try to keep a code written one way. Each time you upgrade a schema of your view, edit it in all already written views. That will help keep your code clear and save a lot time for you in future.
Generally good rule, and how do I write my applications is the rule of small steps. Start with writing a settings and urls, then add one model and one view. When it works, modify - add another models or another views. You won't even notice, when your project becomes bigger and bigger.
And the last useful rule for clarity of all the source. Keep files in folders. If you have two subsites based one one (for example "accounts" and "blogs") create two directories names the same. Remeber to put init.py file in each directory. It's really easy to forget. With this practice it's easy to write models and views dedicated to each category. By the way it's a good practice to keep urls like in a tree structure. Main urls.py should contain only links like this one:
(r'^accounts/', include('your_main_name.accounts.urls')),
and of course all media, static, css and so on. In accounts directory urls keep:
urlpatterns = patterns('your_main_name.accounts.views',
url(r'^$', 'index', name='index'),
)
with all views subdirectories.
Last one - keep code clear with actuall django version. Remeber, that the 3.0 release is comming soon.
Hope this will help.
I find that my process varies depending on a lot of variables, mainly whether I know something will work or if I'm experimenting and also whether I'm developing on my production server or in a development environment.
For example, I often do my development directly on the deployment server (most of my work is for intranet projects so there isn't any security risk, etc). But when I do this I really need to make sure the settings and urls are setup first and that gunicorn and nginx are configured.
If I know something should work, or am setting up a generic base set of code, sometimes I'll do all that coding for views and models before I even get enough setup to even run the development server. But when experimenting with new code I find it's good to be able to test every step of the way, so in that case you need your servers running.
In general I do settings, models, syncdb, views, urls, templates, collectstatic, graphics/aesthetics
In general I leave my base.html very plain until the everything else is working, then I add css/js etc.
I guess my point here is that there isn't really a wrong answer for how you do it, and there isn't even only one best practice (as far as I'm concerned). When you do more work, you'll find what you are comfortable with and it'll even vary from project to project.
Good luck, hopefully you learn to love django!
here is something I do in general,
configure basic settings
configure root url.py
configure settings, url.py for static (media) files
create model
sync db
write views (use simple template, if needed)
once you are done with back end implementation
think about UI
prepare styles, scripts
start working on template implementation

Django: "projects" vs "apps"

I have a fairly complex "product" I'm getting ready to build using Django. I'm going to avoid using the terms "project" and "application" in this context, because I'm not clear on their specific meaning in Django.
Projects can have many apps. Apps can be shared among many projects. Fine.
I'm not reinventing the blog or forum - I don't see any portion of my product being reusable in any context. Intuitively, I would call this one "application." Do I then do all my work in a single "app" folder?
If so... in terms of Django's project.app namespace, my inclination is to use myproduct.myproduct, but of course this isn't allowed (but the application I'm building is my project, and my project is an application!). I'm therefore lead to believe that perhaps I'm supposed to approach Django by building one app per "significant" model, but I don't know where to draw the boundaries in my schema to separate it into apps - I have a lot of models with relatively complex relationships.
I'm hoping there's a common solution to this...
Once you graduate from using startproject and startapp, there's nothing to stop you from combining a "project" and "app" in the same Python package. A project is really nothing more than a settings module, and an app is really nothing more than a models module—everything else is optional.
For small sites, it's entirely reasonable to have something like:
site/
models.py
settings.py
tests.py
urls.py
views.py
Try to answer question: "What does my
application do?". If you cannot answer
in a single sentence, then maybe you can
split it into several apps with cleaner
logic.
I read this thought somewhere soon after I've started to work with django and I find that I ask this question of myself quite often and it helps me.
Your apps don't have to be reusable, they can depend on each other, but they should do one thing.
What is to stop you using myproduct.myproduct? What you need to achieve that roughly consists of doing this:
django-admin.py startproject myproduct
cd myproduct
mkdir myproduct
touch myproduct/__init__.py
touch myproduct/models.py
touch myproduct/views.py
and so on. Would it help if I said views.py doesn't have to be called views.py? Provided you can name, on the python path, a function (usually package.package.views.function_name) it will get handled. Simple as that. All this "project"/"app" stuff is just python packages.
Now, how are you supposed to do it? Or rather, how might I do it? Well, if you create a significant piece of reusable functionality, like say a markup editor, that's when you create a "top level app" which might contain widgets.py, fields.py, context_processors.py etc - all things you might want to import.
Similarly, if you can create something like a blog in a format that is pretty generic across installs, you can wrap it up in an app, with its own template, static content folder etc, and configure an instance of a django project to use that app's content.
There are no hard and fast rules saying you must do this, but it is one of the goals of the framework. The fact that everything, templates included, allows you to include from some common base means your blog should fit snugly into any other setup, simply by looking after its own part.
However, to address your actual concern, yes, nothing says you can't work with the top level project folder. That's what apps do and you can do it if you really want to. I tend not to, however, for several reasons:
Django's default setup doesn't do it.
Often, I want to create a main app, so I create one, usually called website. However, at a later date I might want to develop original functionality just for this site. With a view to making it removable (whether or not I ever do) I tend to then create a separate directory. This also means I can drop said functionality just by unlinking that package from the config and removing the folder, rather than a complex delete the right urls from a global urls.py folder.
Very often, even when I want to make something independent, it needs somewhere to live whilst I look after it / make it independent. Basically the above case, but for stuff I do intend to make generic.
My top level folder often contains a few other things, including but not limited to wsgi scripts, sql scripts etc.
django's management extensions rely on subdirectories. So it makes sense to name packages appropriately.
In short, the reason there is a convention is the same as any other convention - it helps when it comes to others working with your project. If I see fields.py I immediately expect code in it to subclass django's field, whereas if I see inputtypes.py I might not be so clear on what that means without looking at it.
I've found the following blog posts very useful about django applications and projects:
http://www.b-list.org/weblog/2006/sep/10/django-tips-laying-out-application/
http://web.archive.org/web/20080302205555/www.pointy-stick.com/blog/2007/11/09/django-tip-developing-without-projects/
In principle, you have a lot of freedom with django for organizing the source code of your product.
If so... in terms of Django's project.app namespace, my inclination is to usemyproduct.myproduct, but of course this isn't allowed
There is nothing like not allowed. Its your project, no one is restricting you. It is advisable to keep a reasonable name.
I don't see any portion of my product being reusable in any context. Intuitively, I would call this one "application." Do I then do all my work in a single "app" folder?
In a general django project there are many apps (contrib apps) which are used really in every project.
Let us say that your project does only one task and has only a single app (I name it main as thethe project revolves around it and is hardly pluggable). This project too still uses some other apps generally.
Now if you say that your project is using just the one app (INSTALLED_APPS='myproduct') so what is use of project defining the project as project.app, I think you should consider some points:
There are many other things that the code other than the app in a project handles (base static files, base templates, settings....i.e. provides the base).
In the general project.app approach django automatically defines sql schema from models.
Your project would be much easier to be built with the conventional approach.
You may define some different names for urls, views and other files as you wish, but I don't see the need.
You might need to add some applications in future which would be real easy with the conventional django projects which otherwise it may become equally or more difficult and tedious to do.
As far as most of the work being done in the app is concerned, I think that is the case with most of django projects.
Here Django creators points out that difference themselves.
I think that thinking about Apps as they have to be reusable in other projects is good. Also a good way of thinking about Apps in Django provide modern web applications.
Imagine that you are creating big dynamic web app basing on JavaScript.
You can create then in django App named e.g "FrontEnd" <-- in thins app you will display content.
Then you create some backend Apps. E.g App named "Comments" that will store user comments. And "Comments" App will not display anything itself. It will be just API for AJAX requests of your dynamic JS website.
In this way you can always reuse your "Comments" app. You can make it open source without opening source of whole project. And you keep clean logic of your project.

Shifting thinking from CakePHP to Django - a monolithic views file?

I'm trying to get started with Django, and have previously worked with CakePHP, and so my MVC background comes out of that. I'm aware of Django's slightly different MTV architecture, and am fine with the monolithic model files - multiple classes in one file I can handle just fine.
But I'm confused about how to do the views (which are roughly analagous to controllers in MVC, correct?). The examples I've seen just have one views.py that has methods like index(), view(), etc. But if I have a bunch of users that create and own widgets that they can share, for example, I want to have /users/view that runs view() for the users model, and /widgets/view that runs view() for the widgets model.
I don't see any way to separate those out, and don't know what the correct/conventional/right way is to do so. I may just be having trouble wrapping my head around Django's way of doing things, too. Should I have methods in view.py that are user_view and widget_view? That seems very clunky.
Or should I have user_view.py or even user/view.py that contains index() and view()? Could I reference those from the URL routing? How are things generally done with Django and this kind of thing?
This may ultimately be related to (or even solved by) this answer, but I'm asking more as a question of what convention and the right way to think about such things is.
Additionally, shouldn't the docs/examples be clearer on this? I've been impressed by the docs thus far, but I'm pretty sure most web apps will deal with more than one "object," and it seems to me that this would come up pretty often.
Python view files are just Python modules. The views themselves are just functions that can live anywhere you like - the module doesn't even have to be called views.py. The urlconf (in urls.py) can refer to views anywhere at all.
One obvious way of separating things out is into separate applications, which is covered well in the documentation - you can also have separate urls.py files for each app and use include in the main site-level urls.py to include all the sub-files.
But there's nothing to stop you sub-dividing the views in a single app into multiple files - eg by creating a views module, containing a (blank) __init__.py and as many other view files as you like.
Or, if you really do have views associated only with a particular model - and you'd be surprised how seldom that is the case - again, you could make your views classmethods on the model class itself. All a view has to do is to accept a request, and any other parameters, and return a response.

Categories

Resources