Opened 12 years ago

Closed 5 years ago

Last modified 5 years ago

#20456 closed New feature (fixed)

Easier unit testing for class-based views

Reported by: Benoît Bryon Owned by: Felipe Lee
Component: Testing framework Version: dev
Severity: Normal Keywords: cbv test
Cc: bmispelon@…, marc.tamlyn@…, Rémy Hubscher, unai@…, Sergey Fedoseev Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When django users create class-based views, they create custom code. Testing this code matters. Writing unit tests for the custom code (and only for the custom code) is important.

As of Django 1.5, the easiest way to test class-based views is using the builtin test client. But it performs integration tests, i.e. involves middlewares, URL resolvers, decorators...
It is also quite easy to use django.test.RequestFactory and as_view() classmethod. But, since as_view() returns a function, the tests can only check the response. It means the class-based views are tested as a system.

It seems that writing unit tests is possible, i.e. we can write unit tests for class-based views methods.
There is at least one technique which was presented at DjangoCon Europe 2013 Warsaw:

The recipe mentioned above seems to work (to be confirmed). But wouldn't be better if the recipe was documented in Django's documentation (https://docs.djangoproject.com/en/1.5/topics/testing/advanced/ I guess) and tools (setup_view) were builtin Django?

Note: perhaps, it would be even better if setup_view() is not a standalone function but is a method of View class. Something like as_view(), but which returns an instance.

Change History (21)

comment:1 by Baptiste Mispelon, 12 years ago

Cc: bmispelon@… added

comment:2 by Marc Tamlyn, 12 years ago

Cc: marc.tamlyn@… added
Keywords: cbv test added
Owner: changed from nobody to Marc Tamlyn
Status: newassigned
Triage Stage: UnreviewedAccepted

Accepted in principle, not necessarily the design.

comment:3 by Rémy Hubscher, 11 years ago

Cc: Rémy Hubscher added

comment:4 by Benoît Bryon, 11 years ago

I have 2 use cases for this feature:

  • As a library developer, I want to test generic class-based views without having to register them in URLconf.
  • As a project developer, given I override some generic class-based view in order to customize something (such as "get_template_names" or "get_context_data" methods), I want to test only the methods I overrid (I suppose other methods are covered elsewhere).

Here is an example TestCase in django-downloadview: https://github.com/benoitbryon/django-downloadview/blob/6dd090757a8aaad72f9195d22c7933ae97f02a7d/django_downloadview/tests/views.py#L208
The idea is that PathDownloadView customizes get_file() method, so, I want to test that. Notice that django-downloadview is a library that does not provide URLconf, so I appreciate to test views without having to setup some fake URLconf.

comment:5 by Benoît Bryon, 11 years ago

Perhaps this feature would make it possible to simplify tests around Django's generic views:

comment:6 by Unai Zalakain, 11 years ago

Cc: unai@… added

comment:7 by anonymous, 11 years ago

How about something like MyCBView.as_object(request, *args, **kwargs) instead of the setup_view approach?

comment:8 by Baptiste Mispelon, 11 years ago

Has patch: set

Someone made a proposal here: https://github.com/django/django/pull/2368/

comment:9 by Tim Graham, 10 years ago

Patch needs improvement: set

comment:12 by Eron Lloyd, 8 years ago

Any update on this? I'm planning on moving to CBVs but this is concerning for my testing needs.

comment:13 by Tim Graham, 8 years ago

Owner: Marc Tamlyn removed
Status: assignednew

I don't see anyone actively working on it. Feel free to work on it if you like.

comment:14 by Sergey Fedoseev, 6 years ago

Cc: Sergey Fedoseev added

comment:15 by Felipe Lee, 5 years ago

Owner: set to Felipe Lee
Status: newassigned

Looks like there's a repo out there that has a TestCase set up to make testing CBVs easier: https://github.com/revsys/django-test-plus/blob/master/test_plus/test.py#L386

Seems like a good starting point. There's some things about that implementation that I'll probably change a bit. I'll also remove some methods that are very specific to that repo's testing classes.

comment:16 by Felipe Lee, 5 years ago

Patch needs improvement: unset

Brought this ticket up on django developers forum to determine path forward: https://groups.google.com/forum/#!topic/django-developers/IxesUYH5b6A
Based on feedback, implemented changes based on the pr that had been proposed a few comments ago (years ago). New pull request: https://github.com/django/django/pull/11908

comment:17 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

In 31d18225:

Refs #20456 -- Added test for initialization of request/args/kwargs attributes in View.Setup().

comment:18 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

In c2c27867:

Refs #20456 -- Moved initialization of HEAD method based on GET to the View.setup() for generic views.

This will ease unit testing of views since setup will essentially do
everything needed to set the view instance up (other than instantiating
it). Credit for idea goes to Vincent Prouillet.

comment:19 by Carlton Gibson, 5 years ago

Patch needs improvement: set

A few adjustments to the docs PR suggested but looking good.

comment:20 by Felipe Lee, 5 years ago

Patch needs improvement: unset

Made the change a bit ago but I forgot I needed to come in here to remove the "Patch needs improvement" flag. Sorry about that.

comment:21 by Carlton Gibson, 5 years ago

Triage Stage: AcceptedReady for checkin

comment:22 by Carlton Gibson <carlton@…>, 5 years ago

Resolution: fixed
Status: assignedclosed

In a2e96f79:

Fixed #20456 -- Added example of directly testing CBVs in topics docs.

comment:23 by Carlton Gibson <carlton.gibson@…>, 5 years ago

In 87483757:

[3.0.x] Fixed #20456 -- Added example of directly testing CBVs in topics docs.

Backport of a2e96f7969059fb4e621a1cd591fbdd0d4deae2e from master

Note: See TracTickets for help on using tickets.
Back to Top