Difference between revisions of "Python-Django/C2/Testing-in-Django/English"

From Script | Spoken-Tutorial
Jump to: navigation, search
 
Line 25: Line 25:
 
|| To record this tutorial, I am using
 
|| To record this tutorial, I am using
  
* '''Ubuntu Linux OS 16.04'''
+
* '''Ubuntu Linux OS''' 16.04
* '''Python 3.5 '''
+
* '''Python''' 3.5
 
* '''Python 3.4-venv''' or higher and
 
* '''Python 3.4-venv''' or higher and
 
* '''gedit Text Editor '''
 
* '''gedit Text Editor '''
Line 41: Line 41:
 
||  
 
||  
  
* Automated '''testing''' is very useful while coding
+
* '''Automated testing''' is very useful while coding
 
* We can validate our code during the '''development stage''' itself
 
* We can validate our code during the '''development stage''' itself
 
* It is preferred to write '''tests''' in '''Django''' using the '''unit test module'''
 
* It is preferred to write '''tests''' in '''Django''' using the '''unit test module'''
Line 49: Line 49:
  
 
Press CTRl+ALT+T simultaneously
 
Press CTRl+ALT+T simultaneously
||Let us open the '''terminal '''by pressing '''Ctrl''', '''Alt''' and '''T '''keys simultaneously on the keyboard.
+
||Let us open the '''terminal '''by pressing '''Ctrl, Alt''' and '''T '''keys simultaneously on the keyboard.
 
|-
 
|-
 
|| [Terminal]
 
|| [Terminal]
Line 57: Line 57:
 
|-
 
|-
 
|| [Terminal] Type: source myapp_env/bin/activate and press Enter
 
|| [Terminal] Type: source myapp_env/bin/activate and press Enter
|| Activate the '''virtual''' '''environment.'''
+
|| Activate the '''virtual environment.'''
  
 
|-
 
|-
Line 118: Line 118:
  
 
'''from blog.models import Blog'''
 
'''from blog.models import Blog'''
|| So, after the '''TestCase''' import, we will import the '''Blog model.'''
+
|| So, after the '''TestCase import''', we will import the '''Blog model.'''
 
|-
 
|-
 
|| [tests.py] Highlight
 
|| [tests.py] Highlight
Line 177: Line 177:
 
|-
 
|-
 
|| Only narration
 
|| Only narration
|| Let us now run the '''test.'''  
+
|| Let us now '''run''' the '''test.'''  
 
|-
 
|-
 
|| Switch to Terminal
 
|| Switch to Terminal
Line 185: Line 185:
  
 
Type python manage.py test blog [Enter]
 
Type python manage.py test blog [Enter]
|| Then type: '''python <space> manage dot py <space> test <space> blog'''
+
|| Then type '''python <space> manage dot py <space> test <space> blog'''
|-
+
 
|| [Terminal] Highlight python manage.py''' test blog '''
+
|| This '''command''' looks for all the files that starts with '''test''' in the '''app.'''
+
 
|-
 
|-
 
|| [Terminal] Output:
 
|| [Terminal] Output:
Line 211: Line 209:
  
 
self.assertEqual(blog.name, name)'''
 
self.assertEqual(blog.name, name)'''
|| '''Test '''ran successfully as the first and second '''arguments '''which were passed, are equal.
+
|| '''Test ran''' successfully as the first and second '''arguments '''which were passed, are equal.
 
|-
 
|-
 
|| Switch to blog/tests.py
 
|| Switch to blog/tests.py
|| The '''Test''' we ran is very minor.
+
|| The '''Test''' we '''ran''' is very minor.
  
 
So, let us add another '''test case''' for '''blog app.'''
 
So, let us add another '''test case''' for '''blog app.'''
Line 234: Line 232:
  
 
'''blog = Blog.objects.get(id=1)'''
 
'''blog = Blog.objects.get(id=1)'''
|| Get the '''Blog object''' to '''test''' by passing the '''id''' and assigning it to the variable '''blog.'''
+
|| Get the '''Blog object''' to '''test''' by passing the '''id''' and assigning it to the '''variable blog.'''
 
|-
 
|-
 
|| [tests.py] Highlight
 
|| [tests.py] Highlight
Line 246: Line 244:
 
|| Here in '''assertEqual '''the first '''argument''' is a '''method call.'''
 
|| Here in '''assertEqual '''the first '''argument''' is a '''method call.'''
  
The '''method''' is '''was_created_recently '''and it is expected to return '''True.'''
+
The '''method''' is '''was_created_recently '''and it is expected to '''return True.'''
  
 
So our second '''argument''' is a '''boolean True.'''
 
So our second '''argument''' is a '''boolean True.'''
Line 317: Line 315:
  
 
return self.created_on '''>=''' timezone.now() - timezone.timedelta(days=1)
 
return self.created_on '''>=''' timezone.now() - timezone.timedelta(days=1)
|| Locate '''method was_created_recently '''under '''Class Blog.'''
+
|| Now in the '''method was_created_recently '''under the '''Class Blog''', change the '''less than''' sign to '''greater than.'''
 
+
And change the '''less than''' sign to '''greater than.'''
+
 
|-
 
|-
 
|| Press Ctrl+S
 
|| Press Ctrl+S
Line 338: Line 334:
  
 
Highlight '''assertTrue()'''
 
Highlight '''assertTrue()'''
|| Here '''assertTrue method''' is used to check the test the expression is '''TRUE'''
+
|| Here '''assertTrue method''' is used to check the test that the expression is '''TRUE'''
 
|-
 
|-
 
|| Press Ctrl+S
 
|| Press Ctrl+S
Line 358: Line 354:
 
|| Slide: Assertions
 
|| Slide: Assertions
 
||  
 
||  
 +
https://docs.djangoproject.com/en/2.1/topics/testing/tools/#assertions
  
* '''Django TestCase''' provides custom '''assertion methods'''
+
* '''Django TestCase''' provides '''assertion methods'''
 
* These are useful for '''testing web applications'''
 
* These are useful for '''testing web applications'''
 
* Here is the reference link to the documentation of '''methods'''  
 
* Here is the reference link to the documentation of '''methods'''  
 
https://docs.djangoproject.com/en/2.1/topics/testing/tools/#assertions
 
 
|-
 
|-
 
|| Switch to blog/tests.py
 
|| Switch to blog/tests.py
Line 415: Line 410:
  
 
'''blog2 = Blog.objects.get(id=2)'''
 
'''blog2 = Blog.objects.get(id=2)'''
|| Here we get the '''blog object '''2 that we created in the '''setUp().'''
+
|| Here we get the '''blog object '''2 that we created in the '''setUp() method.'''
 
|-
 
|-
 
|| [tests.py] Highlight
 
|| [tests.py] Highlight
  
 
'''self.assertFalse(blog2.was_created_recently())'''
 
'''self.assertFalse(blog2.was_created_recently())'''
|| Let us use '''assertFalse method''' for our '''blog object 2''' in our''' was_created_recently function.'''
+
|| Let us use '''assertFalse method''' for our '''blog object 2''' in our '''was_created_recently function.'''
 
|-
 
|-
 
|| [tests.py] Highlight  
 
|| [tests.py] Highlight  
  
 
'''assertFalse'''
 
'''assertFalse'''
|| Here '''assertFalse method''' is checks the test the expression is False
+
|| Here '''assertFalse method''' is checks the test the expression is '''False'''.
 
|-
 
|-
 
|| Press Ctrl+S
 
|| Press Ctrl+S
Line 431: Line 426:
 
|-
 
|-
 
|| Switch to terminal
 
|| Switch to terminal
|| Switch to '''terminal'''
+
|| Switch to '''terminal'''.
 
|-
 
|-
 
|| [Terminal]Type  
 
|| [Terminal]Type  
Line 438: Line 433:
 
|| Let us now '''run''' a particular '''test case'''.
 
|| Let us now '''run''' a particular '''test case'''.
  
To do that, we have to write the '''method''' name like this:
+
To do that, we have to write the '''method''' name like this.
 
|-
 
|-
 
|| [Terminal] Highlight
 
|| [Terminal] Highlight
Line 485: Line 480:
 
|-
 
|-
 
|| [Terminal] Type deactivate [Enter]
 
|| [Terminal] Type deactivate [Enter]
|| let us now deactivate the '''virtual environment.'''
+
|| Let us now deactivate the '''virtual environment.'''
 
|-
 
|-
 
|| Slide: Test Database
 
|| Slide: Test Database
 
||  
 
||  
 
 
* '''Test runner''' will create an empty '''test database''' with required '''migrations.'''
 
* '''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.
 
* By default, '''database''' will be deleted if all '''tests''' are executed or if '''assertion error''' is raised.
 
  
 
|-
 
|-
 
|| Slide: SetUp and Teardown methods
 
|| Slide: SetUp and Teardown methods
 
||  
 
||  
 
+
* '''SetUp''' and '''TearDown methods''' are '''run''' before and after every '''test''' respectively.
* <u>'''SetUp''' and '''TearDown methods''' are '''run''' before and after every '''test''' respectively.</u>
+
 
* This allows you to set up a basic '''context''' or '''environment''' inside each of the '''tests.'''
 
* This allows you to set up a basic '''context''' or '''environment''' inside each of the '''tests.'''
 
 
 
|-
 
|-
 
|| Slide: SetUp method
 
|| Slide: SetUp method
 
||  
 
||  
 
 
* '''SetUp method runs''' before every '''test.'''
 
* '''SetUp method runs''' before every '''test.'''
 
  
 
|-
 
|-
 
|| Slide: TearDown method
 
|| Slide: TearDown method
 
||
 
||
 
+
* '''TearDown method''' will only be '''called''' if the '''setUp() '''succeeds.
* <u>'''TearDown method''' will only be '''called''' if the '''setUp() '''succeeds.</u>
+
 
+
  
 
|-
 
|-
Line 531: Line 517:
 
|| Slide: Assignment
 
|| Slide: Assignment
 
|| As an assignment,
 
|| As an assignment,
 
 
* Write a '''test case''' for '''Article model''' and '''run''' the '''test.'''
 
* Write a '''test case''' for '''Article model''' and '''run''' the '''test.'''
  

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
  • 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

#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

  • 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

# Create your tests here.


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 TheSpoken Tutorial Projectteam 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.

Contributors and Content Editors

Nancyvarkey, Pravin1389