Difference between revisions of "Python-Django/C2/Testing-in-Django/English"
Pravin1389 (Talk | contribs) (Created page with ".") |
Nancyvarkey (Talk | contribs) |
||
(One intermediate revision by one other user not shown) | |||
Line 1: | Line 1: | ||
− | . | + | '''Django/C2/Testing in Django/English''' |
+ | |||
+ | '''Title of script: '''Testing in Django | ||
+ | |||
+ | '''Keywords: '''Video tutorial, Django write test, Django run test | ||
+ | |||
+ | |||
+ | |||
+ | {| border = 1 | ||
+ | |- | ||
+ | || Visual cue | ||
+ | || Narration | ||
+ | |- | ||
+ | || Slide: Writing Tests in Django | ||
+ | || Hello and welcome to the spoken tutorial on “'''Testing''' in '''Django'''“ | ||
+ | |- | ||
+ | || Slide: Learning Objectives | ||
+ | || In this tutorial, we will learn to | ||
+ | |||
+ | * Write '''tests''' in''' Django '''and | ||
+ | * '''Run''' the '''tests''' in '''Django''' | ||
+ | |||
+ | |- | ||
+ | || Slide: System Requirements | ||
+ | || To record this tutorial, I am using | ||
+ | |||
+ | * '''Ubuntu Linux OS''' 16.04 | ||
+ | * '''Python''' 3.5 | ||
+ | * '''Python 3.4-venv''' or higher and | ||
+ | * '''gedit Text Editor ''' | ||
+ | |||
+ | |- | ||
+ | || Slide: Prerequisites | ||
+ | || To follow this tutorial, you need to know | ||
+ | |||
+ | * How to create '''Models''' in '''Django ''' | ||
+ | * If not, then please go through the prerequisite '''Django''' tutorials on this website. | ||
+ | |||
+ | |- | ||
+ | || Slide: Testing in Django | ||
+ | || | ||
+ | |||
+ | * '''Automated testing''' is very useful while coding | ||
+ | * We can validate our code during the '''development stage''' itself | ||
+ | * It is preferred to write '''tests''' in '''Django''' using the '''unit test module''' | ||
+ | |||
+ | |- | ||
+ | || Open a Terminal window | ||
+ | |||
+ | Press CTRl+ALT+T simultaneously | ||
+ | ||Let us open the '''terminal '''by pressing '''Ctrl, Alt''' and '''T '''keys simultaneously on the keyboard. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | cd '''my-django '''[Enter] | ||
+ | ||Using the '''cd command''', go to the folder '''my hyphen django''' | ||
+ | |- | ||
+ | || [Terminal] Type: source myapp_env/bin/activate and press Enter | ||
+ | || Activate the '''virtual environment.''' | ||
+ | |||
+ | |- | ||
+ | || [Terminal] cd mysite and Press Enter | ||
+ | ||Now go to the '''mysite''' folder using '''cd''' command | ||
+ | |- | ||
+ | || | ||
+ | ||Here onwards, please remember to press the '''Enter''' key after typing each '''command'''. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | Type gedit blog/tests.py & [Enter] | ||
+ | || Let us write the '''test case''' for our '''blog''' app. | ||
+ | |||
+ | Type''' gedit <space> blog slash tests dot py <space> ampersand''' | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight | ||
+ | |||
+ | '''from django.test import TestCase''' | ||
+ | |||
+ | '''<nowiki>#Create your tests here.</nowiki>''' | ||
+ | || We are now in '''tests.py''' file | ||
+ | |||
+ | Here we import '''TestCase '''from '''Django’s test module. ''' | ||
+ | |||
+ | '''TestCase '''is a '''subclass''' of '''unit test.''' | ||
+ | |||
+ | A '''test case''' checks whether a given set of inputs leads to an expected set of results. | ||
+ | |- | ||
+ | || [tests.py] Type: | ||
+ | |||
+ | class BlogTestCase(TestCase): def setUp(self): | ||
+ | |||
+ | Blog.objects.create(name='New Blog') | ||
+ | |||
+ | def test_blog_created(self): | ||
+ | |||
+ | blog = Blog.objects.get(id=1) | ||
+ | |||
+ | name = 'New Blog' | ||
+ | |||
+ | self.assertEqual(blog.name, name) | ||
+ | || Let us now add a '''class BlogTestCase''' as shown here. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight '''class BlogTestCase(TestCase):''' | ||
+ | || Here, we have created a '''class BlogTestCase''' to '''test''' our '''Blog model.''' | ||
+ | |||
+ | It is a '''subclass''' of '''TestCase.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''from django.test import TestCase''' | ||
+ | || '''class TestCase '''is used for writing '''tests''' in '''Django. ''' | ||
+ | |- | ||
+ | || [tests.py] Type: | ||
+ | |||
+ | '''from blog.models import Blog''' | ||
+ | || So, after the '''TestCase import''', we will import the '''Blog model.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''def setUp(self):''' | ||
+ | || Whenever the '''test runs''', first it will call the '''setUp method.''' | ||
+ | |||
+ | '''setUp runs''' once for every '''test method''' to '''setup''' clean data. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight '''Blog.objects.create(name= 'New Blog')''' | ||
+ | || So in the '''setUp,''' a '''blog''' is created. | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''def test_blog_created(self):''' | ||
+ | || Here a '''method test_blog_created '''is defined to '''test''' the '''blog''' which is created. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight def '''test'''_blog_created(self): | ||
+ | || '''class TestCase methods '''begins with the name '''test.''' | ||
+ | |||
+ | '''Django’s test runner runs''' these '''test methods.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''blog = Blog.objects.get(id=1)''' | ||
+ | || Here we get the '''blog object '''that we created in the '''setUp()'''. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight '''id=1''' | ||
+ | || '''ids''' are uniquely generated for each '''blog.''' | ||
+ | |||
+ | But in complex cases, many '''blogs''' are created and deleted. | ||
+ | |- | ||
+ | || [tests.py] Highlight '''name = 'New Blog'''' | ||
+ | || Let’s define a '''variable '''as '''string “New Blog”.''' | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight '''self.assertEqual(blog.name, name)''' | ||
+ | || '''assertEqual''' is a '''method''' provided by '''TestCase.''' | ||
+ | |||
+ | It checks whether the two '''arguments''' passed here are equal or not. | ||
+ | |||
+ | Here we have passed the '''blog''' name and expected '''string New Blog.''' | ||
+ | |||
+ | If the '''condition''' does not evaluate as expected, then the '''test '''will fail and report the error. | ||
+ | |- | ||
+ | || Highlight the complete code | ||
+ | || Now, we have added a '''TestCase.''' | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Only narration | ||
+ | || Let us now '''run''' the '''test.''' | ||
+ | |- | ||
+ | || Switch to Terminal | ||
+ | || Switch to the '''terminal'''. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | Type python manage.py test blog [Enter] | ||
+ | || Then type '''python <space> manage dot py <space> test <space> blog''' | ||
+ | |||
+ | |- | ||
+ | || [Terminal] Output: | ||
+ | |||
+ | '''Creating test database for alias 'default'... | ||
+ | |||
+ | System check identified no issues (0 silenced). | ||
+ | |||
+ | <nowiki>-------------------------------------------------------------</nowiki>''' | ||
+ | |||
+ | '''Ran 1 test in 0.002sOKDestroying test database for alias 'default'...''' | ||
+ | || Here, we can see the output. | ||
+ | |||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | def test_blog_created(self): | ||
+ | |||
+ | blog = Blog.objects.get(id=1) | ||
+ | |||
+ | name = 'New Blog' ''' | ||
+ | |||
+ | self.assertEqual(blog.name, name)''' | ||
+ | || '''Test ran''' successfully as the first and second '''arguments '''which were passed, are equal. | ||
+ | |- | ||
+ | || Switch to blog/tests.py | ||
+ | || The '''Test''' we '''ran''' is very minor. | ||
+ | |||
+ | So, let us add another '''test case''' for '''blog app.''' | ||
+ | |- | ||
+ | || [tests.py]Type: | ||
+ | |||
+ | def test_was_created_recently(self): | ||
+ | |||
+ | blog = Blog.objects.get(id=1) | ||
+ | |||
+ | is_created_recently = True | ||
+ | |||
+ | self.assertEqual(blog.was_created_recently(), is_created_recently) | ||
+ | |||
+ | || Add a '''method''' in '''BlogTestCase''' as shown here. | ||
+ | |||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''blog = Blog.objects.get(id=1)''' | ||
+ | || Get the '''Blog object''' to '''test''' by passing the '''id''' and assigning it to the '''variable blog.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''is_created_recently = True''' | ||
+ | || Assign the value '''True''' to '''is_created_recently''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''self.assertEqual (blog.was_created_recently(), is_created_recently)''' | ||
+ | || Here in '''assertEqual '''the first '''argument''' is a '''method call.''' | ||
+ | |||
+ | The '''method''' is '''was_created_recently '''and it is expected to '''return True.''' | ||
+ | |||
+ | So our second '''argument''' is a '''boolean True.''' | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Switch to Terminal | ||
+ | || Switch to the '''terminal'''. | ||
+ | |- | ||
+ | || [Terminal] Type python manage.py test blog [Enter] | ||
+ | || Now, recall the previous '''command''' to run the '''test.''' | ||
+ | |- | ||
+ | || [Terminal] Output: '''Ran 2 tests in 0.003s''' | ||
+ | || The output says, '''Ran 2 tests. ''' | ||
+ | |||
+ | '''assertEqual function '''in '''method test_was_created_recently '''returns '''TRUE.''' | ||
+ | |||
+ | As the two '''arguments''' passed are equal, the 2nd '''test '''also ran successfully. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | || Next open the '''models.py''' file. | ||
+ | |||
+ | We will change the logic of '''was_created_recently method '''in this file. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | Type gedit blog/models.py & [Enter] | ||
+ | || Type '''gedit <space> blog slash models dot py <space> ampersand''' | ||
+ | |- | ||
+ | || [models.py]Type: | ||
+ | |||
+ | def was_created_recently(self): | ||
+ | |||
+ | return self.created_on''' <= '''timezone.now() - timezone.timedelta(days=1) | ||
+ | |||
+ | || We are now in '''models.py''' file. | ||
+ | |||
+ | In the '''class blog''', locate the '''was_created_recently method.''' | ||
+ | |||
+ | In the '''return statement,''' change the sign '''greater than''' to '''less than.''' | ||
+ | |- | ||
+ | || [models.py] Highlight | ||
+ | |||
+ | return self.created_on '''<=''' timezone.now() - timezone.timedelta(days=1) | ||
+ | || Since the '''blog object '''was not created recently, the '''method''' returns '''False'''. | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Switch to Terminal | ||
+ | || Switch to the '''terminal'''. | ||
+ | |- | ||
+ | || [Terminal] Type python manage.py test blog [Enter] | ||
+ | || And '''run''' the '''test''' again. | ||
+ | |- | ||
+ | || [Terminal] Output: '''AssertionError: False!= True''' | ||
+ | || The output shows an '''assertion error.''' | ||
+ | |||
+ | '''was_created_recently method '''returns '''False '''instead of '''True.''' | ||
+ | |||
+ | This shows the power of having '''tests'''. | ||
+ | |||
+ | In case anyone modifies the code incorrectly later on, then the '''tests''' will help to detect it. | ||
+ | |- | ||
+ | || Switch to models.py | ||
+ | || Switch back to '''models.py''' file to revert the changes. | ||
+ | |- | ||
+ | || [models.py] Highlight | ||
+ | |||
+ | return self.created_on '''>=''' timezone.now() - timezone.timedelta(days=1) | ||
+ | || Now in the '''method was_created_recently '''under the '''Class Blog''', change the '''less than''' sign to '''greater than.''' | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || [tests.py] Type: | ||
+ | |||
+ | def test_was_created_recently(self): | ||
+ | |||
+ | blog = Blog.objects.get(id=1) | ||
+ | |||
+ | self.assertTrue(blog.was_created_recently()) | ||
+ | || Switch to the '''tests.py''' file. | ||
+ | |||
+ | In the '''function test_was_created_recently, '''modify the code as shown. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | Highlight '''assertTrue()''' | ||
+ | || Here '''assertTrue method''' is used to check the test that the expression is '''TRUE''' | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Switch to Terminal | ||
+ | || Switch to the '''terminal'''. | ||
+ | |- | ||
+ | || [Terminal] Type python manage.py test blog [Enter] | ||
+ | || And run the''' test app.''' | ||
+ | |- | ||
+ | || [Terminal] Highlight | ||
+ | |||
+ | '''Ran 2 tests in 0.003s''' | ||
+ | |||
+ | '''OK''' | ||
+ | || The '''test ran''' without any errors, satisfying the given '''condition.''' | ||
+ | |- | ||
+ | || Slide: Assertions | ||
+ | || | ||
+ | https://docs.djangoproject.com/en/2.1/topics/testing/tools/#assertions | ||
+ | |||
+ | * '''Django TestCase''' provides '''assertion methods''' | ||
+ | * These are useful for '''testing web applications''' | ||
+ | * Here is the reference link to the documentation of '''methods''' | ||
+ | |- | ||
+ | || Switch to blog/tests.py | ||
+ | || Switch to '''tests.py '''file. | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | |||
+ | from django.test import TestCase | ||
+ | |||
+ | from blog.models import Blog | ||
+ | |||
+ | <nowiki># Create your tests here.</nowiki> | ||
+ | |||
+ | |||
+ | class BlogTestCase(TestCase): | ||
+ | |||
+ | def setUp(self): | ||
+ | |||
+ | Blog.objects.create(name='Blog1') | ||
+ | |||
+ | Blog.objects.create(name='Blog2') | ||
+ | |||
+ | |||
+ | def test_blog_created(self): | ||
+ | |||
+ | blog = Blog.objects.get(id=1) | ||
+ | |||
+ | name = 'New Blog' | ||
+ | |||
+ | self.assertEqual(blog.name, name) | ||
+ | |||
+ | |||
+ | def test_was_created_recently(self): | ||
+ | |||
+ | blog1 = Blog.objects.get(id=1) | ||
+ | |||
+ | blog2 = Blog.objects.get(id=2) | ||
+ | |||
+ | self.assertTrue(blog1.was_created_recently()) | ||
+ | |||
+ | self.assertFalse(blog2.was_created_recently()) | ||
+ | || Modify the code as shown here. | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''Blog.objects.create(name='Blog2')''' | ||
+ | || Here, we created a''' blog object blog 2''' in '''setUp() method.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''blog2 = Blog.objects.get(id=2)''' | ||
+ | || Here we get the '''blog object '''2 that we created in the '''setUp() method.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''self.assertFalse(blog2.was_created_recently())''' | ||
+ | || Let us use '''assertFalse method''' for our '''blog object 2''' in our '''was_created_recently function.''' | ||
+ | |- | ||
+ | || [tests.py] Highlight | ||
+ | |||
+ | '''assertFalse''' | ||
+ | || Here '''assertFalse method''' is checks the test the expression is '''False'''. | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Switch to terminal | ||
+ | || Switch to '''terminal'''. | ||
+ | |- | ||
+ | || [Terminal]Type | ||
+ | |||
+ | python manage.py test blog.tests.BlogTestCase.test_was_created_recently [Enter] | ||
+ | || Let us now '''run''' a particular '''test case'''. | ||
+ | |||
+ | To do that, we have to write the '''method''' name like this. | ||
+ | |- | ||
+ | || [Terminal] Highlight | ||
+ | |||
+ | '''AssertionError: True is not False''' | ||
+ | || On execution, we can see the output for the '''test case.''' | ||
+ | |||
+ | '''AssertionError''' raised an '''error''' message '''True is not False.''' | ||
+ | |||
+ | This is because the '''was_created_recently''' returns '''TRUE '''and we are expecting '''FALSE'''. | ||
+ | |- | ||
+ | || Switch to blog/tests.py | ||
+ | || Switch to '''tests.py''' file to correct the '''assertion error.''' | ||
+ | |- | ||
+ | || [tests.py] | ||
+ | |||
+ | def test_was_created_recently(self): | ||
+ | |||
+ | blog1 = Blog.objects.get(id=1) | ||
+ | |||
+ | blog2 = Blog.objects.get(id=2) | ||
+ | |||
+ | self.assertTrue(blog1.was_created_recently()) | ||
+ | |||
+ | '''self.assertTrue(blog2.was_created_recently())''' | ||
+ | || Change '''assertFalse''' to '''assertTrue.''' | ||
+ | |- | ||
+ | || Press Ctrl+S | ||
+ | || Save the file. | ||
+ | |- | ||
+ | || Switch to terminal | ||
+ | || Switch to '''terminal.''' | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | Type python manage.py test blog.tests.BlogTestCase.test_was_created_recently [Enter] | ||
+ | || And execute the specific '''test case''' again. | ||
+ | |- | ||
+ | || [Terminal] | ||
+ | |||
+ | Highlighting the output | ||
+ | || The '''test ran''' successfully without any '''assertion errors.''' | ||
+ | |- | ||
+ | || Switch to Terminal | ||
+ | || This is how we should perform the '''testing''' in '''Django.''' | ||
+ | |- | ||
+ | || [Terminal] Type deactivate [Enter] | ||
+ | || Let us now deactivate the '''virtual environment.''' | ||
+ | |- | ||
+ | || Slide: Test Database | ||
+ | || | ||
+ | * '''Test runner''' will create an empty '''test database''' with required '''migrations.''' | ||
+ | * By default, '''database''' will be deleted if all '''tests''' are executed or if '''assertion error''' is raised. | ||
+ | |||
+ | |- | ||
+ | || Slide: SetUp and Teardown methods | ||
+ | || | ||
+ | * '''SetUp''' and '''TearDown methods''' are '''run''' before and after every '''test''' respectively. | ||
+ | * This allows you to set up a basic '''context''' or '''environment''' inside each of the '''tests.''' | ||
+ | |- | ||
+ | || Slide: SetUp method | ||
+ | || | ||
+ | * '''SetUp method runs''' before every '''test.''' | ||
+ | |||
+ | |- | ||
+ | || Slide: TearDown method | ||
+ | || | ||
+ | * '''TearDown method''' will only be '''called''' if the '''setUp() '''succeeds. | ||
+ | |||
+ | |- | ||
+ | || | ||
+ | || With this, we come to the end of this tutorial. | ||
+ | |||
+ | Let us summarize. | ||
+ | |- | ||
+ | || Slide: Summary | ||
+ | || In this tutorial, we have learnt to | ||
+ | |||
+ | * Write '''tests''' in '''Django''' | ||
+ | * '''Run tests''' in '''Django''' | ||
+ | |||
+ | |- | ||
+ | || Slide: Assignment | ||
+ | || As an assignment, | ||
+ | * Write a '''test case''' for '''Article model''' and '''run''' the '''test.''' | ||
+ | |||
+ | |- | ||
+ | || Slide: About Spoken Tutorial project | ||
+ | || The video at the following link summarises the Spoken Tutorial project. | ||
+ | |||
+ | |||
+ | Please download and watch it. | ||
+ | |- | ||
+ | || Slide: Spoken Tutorial workshops | ||
+ | || The'''Spoken Tutorial Project'''team conducts workshops and gives certificates. | ||
+ | |||
+ | |||
+ | For more details, please write to us. | ||
+ | |- | ||
+ | || Slide: Forum for specific questions: | ||
+ | || Please post your timed queries in this Forum. | ||
+ | |- | ||
+ | || Slide: FOSSEE to answer questions | ||
+ | || Please post your general or technical questions in this Forum. | ||
+ | |- | ||
+ | || Slide: Acknowledgement | ||
+ | || Spoken Tutorial Project is funded by NMEICT, MHRD, Government of India. | ||
+ | |||
+ | More information on this mission is available at this link. | ||
+ | |- | ||
+ | || Slide: Thanks Slide | ||
+ | || This script has been contributed by Thiagarajar College of Engineering and the FOSSEE Project, IIT Bombay. | ||
+ | |||
+ | The video has been recorded by Praveen from Spoken Tutorial Project, IIT Bombay. | ||
+ | |||
+ | Thanks for watching. | ||
+ | |- | ||
+ | |} |
Latest revision as of 15:01, 14 October 2019
Django/C2/Testing in Django/English
Title of script: Testing in Django
Keywords: Video tutorial, Django write test, Django run test
Visual cue | Narration |
Slide: Writing Tests in Django | Hello and welcome to the spoken tutorial on “Testing in Django“ |
Slide: Learning Objectives | In this tutorial, we will learn to
|
Slide: System Requirements | To record this tutorial, I am using
|
Slide: Prerequisites | To follow this tutorial, you need to know
|
Slide: Testing in Django |
|
Open a Terminal window
Press CTRl+ALT+T simultaneously |
Let us open the terminal by pressing Ctrl, Alt and T keys simultaneously on the keyboard. |
[Terminal]
cd my-django [Enter] |
Using the cd command, go to the folder my hyphen django |
[Terminal] Type: source myapp_env/bin/activate and press Enter | Activate the virtual environment. |
[Terminal] cd mysite and Press Enter | Now go to the mysite folder using cd command |
Here onwards, please remember to press the Enter key after typing each command. | |
[Terminal]
Type gedit blog/tests.py & [Enter] |
Let us write the test case for our blog app.
Type gedit <space> blog slash tests dot py <space> ampersand |
[tests.py]
Highlight from django.test import TestCase #Create your tests here. |
We are now in tests.py file
Here we import TestCase from Django’s test module. TestCase is a subclass of unit test. A test case checks whether a given set of inputs leads to an expected set of results. |
[tests.py] Type:
class BlogTestCase(TestCase): def setUp(self): Blog.objects.create(name='New Blog') def test_blog_created(self): blog = Blog.objects.get(id=1) name = 'New Blog' self.assertEqual(blog.name, name) |
Let us now add a class BlogTestCase as shown here. |
[tests.py]
Highlight class BlogTestCase(TestCase): |
Here, we have created a class BlogTestCase to test our Blog model.
It is a subclass of TestCase. |
[tests.py] Highlight
from django.test import TestCase |
class TestCase is used for writing tests in Django. |
[tests.py] Type:
from blog.models import Blog |
So, after the TestCase import, we will import the Blog model. |
[tests.py] Highlight
def setUp(self): |
Whenever the test runs, first it will call the setUp method.
setUp runs once for every test method to setup clean data. |
[tests.py]
Highlight Blog.objects.create(name= 'New Blog') |
So in the setUp, a blog is created. |
[tests.py] Highlight
def test_blog_created(self): |
Here a method test_blog_created is defined to test the blog which is created. |
[tests.py]
Highlight def test_blog_created(self): |
class TestCase methods begins with the name test.
Django’s test runner runs these test methods. |
[tests.py] Highlight
blog = Blog.objects.get(id=1) |
Here we get the blog object that we created in the setUp(). |
[tests.py]
Highlight id=1 |
ids are uniquely generated for each blog.
But in complex cases, many blogs are created and deleted. |
[tests.py] Highlight name = 'New Blog' | Let’s define a variable as string “New Blog”. |
[tests.py]
Highlight self.assertEqual(blog.name, name) |
assertEqual is a method provided by TestCase.
It checks whether the two arguments passed here are equal or not. Here we have passed the blog name and expected string New Blog. If the condition does not evaluate as expected, then the test will fail and report the error. |
Highlight the complete code | Now, we have added a TestCase. |
Press Ctrl+S | Save the file. |
Only narration | Let us now run the test. |
Switch to Terminal | Switch to the terminal. |
[Terminal]
Type python manage.py test blog [Enter] |
Then type python <space> manage dot py <space> test <space> blog |
[Terminal] Output:
Creating test database for alias 'default'... System check identified no issues (0 silenced). ------------------------------------------------------------- Ran 1 test in 0.002sOKDestroying test database for alias 'default'... |
Here, we can see the output. |
[tests.py] Highlight
def test_blog_created(self): blog = Blog.objects.get(id=1) name = 'New Blog' self.assertEqual(blog.name, name) |
Test ran successfully as the first and second arguments which were passed, are equal. |
Switch to blog/tests.py | The Test we ran is very minor.
So, let us add another test case for blog app. |
[tests.py]Type:
def test_was_created_recently(self): blog = Blog.objects.get(id=1) is_created_recently = True self.assertEqual(blog.was_created_recently(), is_created_recently) |
Add a method in BlogTestCase as shown here. |
[tests.py] Highlight
blog = Blog.objects.get(id=1) |
Get the Blog object to test by passing the id and assigning it to the variable blog. |
[tests.py] Highlight
is_created_recently = True |
Assign the value True to is_created_recently |
[tests.py] Highlight
self.assertEqual (blog.was_created_recently(), is_created_recently) |
Here in assertEqual the first argument is a method call.
The method is was_created_recently and it is expected to return True. So our second argument is a boolean True. |
Press Ctrl+S | Save the file. |
Switch to Terminal | Switch to the terminal. |
[Terminal] Type python manage.py test blog [Enter] | Now, recall the previous command to run the test. |
[Terminal] Output: Ran 2 tests in 0.003s | The output says, Ran 2 tests.
assertEqual function in method test_was_created_recently returns TRUE. As the two arguments passed are equal, the 2nd test also ran successfully. |
[Terminal] | Next open the models.py file.
We will change the logic of was_created_recently method in this file. |
[Terminal]
Type gedit blog/models.py & [Enter] |
Type gedit <space> blog slash models dot py <space> ampersand |
[models.py]Type:
def was_created_recently(self): return self.created_on <= timezone.now() - timezone.timedelta(days=1) |
We are now in models.py file.
In the class blog, locate the was_created_recently method. In the return statement, change the sign greater than to less than. |
[models.py] Highlight
return self.created_on <= timezone.now() - timezone.timedelta(days=1) |
Since the blog object was not created recently, the method returns False. |
Press Ctrl+S | Save the file. |
Switch to Terminal | Switch to the terminal. |
[Terminal] Type python manage.py test blog [Enter] | And run the test again. |
[Terminal] Output: AssertionError: False!= True | The output shows an assertion error.
was_created_recently method returns False instead of True. This shows the power of having tests. In case anyone modifies the code incorrectly later on, then the tests will help to detect it. |
Switch to models.py | Switch back to models.py file to revert the changes. |
[models.py] Highlight
return self.created_on >= timezone.now() - timezone.timedelta(days=1) |
Now in the method was_created_recently under the Class Blog, change the less than sign to greater than. |
Press Ctrl+S | Save the file. |
[tests.py] Type:
def test_was_created_recently(self): blog = Blog.objects.get(id=1) self.assertTrue(blog.was_created_recently()) |
Switch to the tests.py file.
In the function test_was_created_recently, modify the code as shown. |
[tests.py]
Highlight assertTrue() |
Here assertTrue method is used to check the test that the expression is TRUE |
Press Ctrl+S | Save the file. |
Switch to Terminal | Switch to the terminal. |
[Terminal] Type python manage.py test blog [Enter] | And run the test app. |
[Terminal] Highlight
Ran 2 tests in 0.003s OK |
The test ran without any errors, satisfying the given condition. |
Slide: Assertions |
https://docs.djangoproject.com/en/2.1/topics/testing/tools/#assertions
|
Switch to blog/tests.py | Switch to tests.py file. |
[tests.py]
from blog.models import Blog # Create your tests here.
def setUp(self): Blog.objects.create(name='Blog1') Blog.objects.create(name='Blog2')
blog = Blog.objects.get(id=1) name = 'New Blog' self.assertEqual(blog.name, name)
blog1 = Blog.objects.get(id=1) blog2 = Blog.objects.get(id=2) self.assertTrue(blog1.was_created_recently()) self.assertFalse(blog2.was_created_recently()) |
Modify the code as shown here. |
[tests.py] Highlight
Blog.objects.create(name='Blog2') |
Here, we created a blog object blog 2 in setUp() method. |
[tests.py] Highlight
blog2 = Blog.objects.get(id=2) |
Here we get the blog object 2 that we created in the setUp() method. |
[tests.py] Highlight
self.assertFalse(blog2.was_created_recently()) |
Let us use assertFalse method for our blog object 2 in our was_created_recently function. |
[tests.py] Highlight
assertFalse |
Here assertFalse method is checks the test the expression is False. |
Press Ctrl+S | Save the file. |
Switch to terminal | Switch to terminal. |
[Terminal]Type
python manage.py test blog.tests.BlogTestCase.test_was_created_recently [Enter] |
Let us now run a particular test case.
To do that, we have to write the method name like this. |
[Terminal] Highlight
AssertionError: True is not False |
On execution, we can see the output for the test case.
AssertionError raised an error message True is not False. This is because the was_created_recently returns TRUE and we are expecting FALSE. |
Switch to blog/tests.py | Switch to tests.py file to correct the assertion error. |
[tests.py]
def test_was_created_recently(self): blog1 = Blog.objects.get(id=1) blog2 = Blog.objects.get(id=2) self.assertTrue(blog1.was_created_recently()) self.assertTrue(blog2.was_created_recently()) |
Change assertFalse to assertTrue. |
Press Ctrl+S | Save the file. |
Switch to terminal | Switch to terminal. |
[Terminal]
Type python manage.py test blog.tests.BlogTestCase.test_was_created_recently [Enter] |
And execute the specific test case again. |
[Terminal]
Highlighting the output |
The test ran successfully without any assertion errors. |
Switch to Terminal | This is how we should perform the testing in Django. |
[Terminal] Type deactivate [Enter] | Let us now deactivate the virtual environment. |
Slide: Test Database |
|
Slide: SetUp and Teardown methods |
|
Slide: SetUp method |
|
Slide: TearDown method |
|
With this, we come to the end of this tutorial.
Let us summarize. | |
Slide: Summary | In this tutorial, we have learnt to
|
Slide: Assignment | As an assignment,
|
Slide: About Spoken Tutorial project | The video at the following link summarises the Spoken Tutorial project.
|
Slide: Spoken Tutorial workshops | TheSpoken Tutorial Projectteam conducts workshops and gives certificates.
|
Slide: Forum for specific questions: | Please post your timed queries in this Forum. |
Slide: FOSSEE to answer questions | Please post your general or technical questions in this Forum. |
Slide: Acknowledgement | Spoken Tutorial Project is funded by NMEICT, MHRD, Government of India.
More information on this mission is available at this link. |
Slide: Thanks Slide | This script has been contributed by Thiagarajar College of Engineering and the FOSSEE Project, IIT Bombay.
The video has been recorded by Praveen from Spoken Tutorial Project, IIT Bombay. Thanks for watching. |