A Python project with coding framework and unit testing for beginners | Engineering Tech | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

A Python project with coding framework and unit testing for beginners

teacher avatar Engineering Tech, Big Data, Cloud and AI Solution Architec

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

27 Lessons (1h 48m)
    • 1. Introduction

    • 2. What is Python ?

    • 3. Installing Python

    • 4. Installing PyCharm

    • 5. Python basics

    • 6. Python dictionary

    • 7. Python List and Tuple

    • 8. Organizing code with Objects and Methods

    • 9. Initializing variables with Python constructor

    • 10. Logging using basic config

    • 11. Logging using file config

    • 12. Having multiple loggers in an application

    • 13. Error Handling with try except and raise

    • 14. Reading configuration from properties file

    • 15. Installing PostgreSQL

    • 16. Reading from and writing to Postgres

    • 17. Organizing code further

    • 18. Handling the unique key constraint error

    • 19. Reading data from a JSON

    • 20. Writing JSON file data to PostgreSQL

    • 21. What is REST?

    • 22. Understanding how REST will be used in the application

    • 23. Creating a REST API to fetch course list

    • 24. Creating a REST API to store course information

    • 25. Python unittest package

    • 26. Data and error testing

    • 27. Unit testing with PyTest

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

Learn how to code and unit test Python applications in a real world project. Go beyond the basics by solving a real world use case step by step. This course is designed for Python beginners who want to transition for academic background to a real world developer role !

Course structure :

  • Python basics

  • Organizing code with Classes and Modules

  • Python logging

  • Python error handling

  • Python PostgreSQL database interaction

  • Create REST API using Python
  • Reading configuration from property file

  • Unit testing

You will learn the above concepts by building a real world file processing application. No prior Python knowledge required.

Prerequisites :

  • Basic programming skillsĀ 
  • Basic knowledge of SQL queries

Meet Your Teacher

Teacher Profile Image

Engineering Tech

Big Data, Cloud and AI Solution Architec


Hello, I'm Engineering.

See full profile

Related Skills

Technology Python Data Science

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Introduction: The best way to learn any programming languages by applying the concepts in solving real-world use case. Welcome to this course of your Python project using real-world coding framework and unit testing. This course will take you from your academic background to a real-world Python developer role. You'll learn how to organize the code, how to do logging and error handling, how to read configuration from properties fail, and various other concepts. In the real world is a Python developer. You will be testing your code before handing it over to the acuity. In this course, you'll learn how to unit test your Python application using various techniques. This course is very hands-on and we abused by Chuck for all our development one, PyCharm is a popular idea in the real world. You'll start from basic Python concepts and step-by-step understand how to build an application following some of the industry best practices is part of the project work. You learn how to interact with a database from a Python application. You'll also learn how to build rest API using Python, a popular way of extending data in the real world. You do not need to have any prior knowledge in Python. However, if your basic programming skills and some database knowledge, then we're definitely succeed in this course. Let's dive in and get started. 2. What is Python ?: Python is a powerful programming language that can be used in many different ways, in many different areas. You can build a wide variety of applications using Python. Pretty much everything that you've seen the real world. It could be website or an application, or be Geta, spark, AI and machine learning blockchain. All kinds of applications can be built using Python. Python is a high-level programming language. That means you do not have to deal with low-level machine specific details. It's an interpreted language. It doesn't require completion. You can write the code and run it in any Python. And moment, python is dynamically typed. That also makes it very concise and readable. Dynamic languages have smaller source footprint. Because Python is interpreted, it provides powerful prototyping and light coating opportunity. You can log into any Python environment, start coding and you'll see the output. You do not need to compiler create jagged like many other programming languages. 3. Installing Python: Go to the Python officer loop site and download. Python will download the latest version, which is 3.9. Once downloaded, click on the installer. And you are doubt Python to classify and installed. Once installation is complete. Go to the command prompt, can verify. Python 3.9 is available of this machine. 4. Installing PyCharm: Let's now installed PyCharm, which is one of the most popular IDEs for Python development. Go to JetBrains website and download the Community Edition. Once downloaded, click on the installer. You can select the 64-bit launcher shortcuts that will be created on your desktop. Once finished, the Lord pyjamas. No need to import setting. Let's create a new project. Directly. Specify that, but let's give the project a Mm. It takes some time to create a virtual environment. You'll get an isolated environment to manage your project dependencies. By default, you'll get a main.out. We the main method. Click on this green arrow to run it down. You can see the sample code output high Python pie chart in the console. Let's add another print statement. Relied a breakpoint. Simply click here, and then it would run up to that point. It printed up to that plane, and you can click and execute the next line. So this is how we can debug python programming. 5. Python basics: Let's look at this default file that creates, we'll remove all the comments. In a Python program. The starting point is this if block, which takes Name Is equal to men. That's where the program execution begins. You could also write this edge, men. And this is the main method. And from here you call the min. That is the way you would see most of the Python programs written in the real world. But it's okay to have a different name for domain metadata. Let's learn some Python basics. We'll do our Python programming within this main method. Biotin spacing and indentation matters. You can't have print like this. It'll give an expected an indented block. So all the methods are the different blocks, like if block and the blocks, the start with indentation. And wherever they ended this an edge, the method ends or the loop ends. We can have a print statement here also. These two lines are part of this if loop. Python supports all kinds of arithmetic operations, like addition, subtraction. Let's declare two variables. In Python, you can declare variables without giving the datatype. Regard output three-plus four. Heavy string value populated with a. Python will complain. So depending on what value we are populating, Python will take that data type list to the popular data type in Python. Collection like an adder, where you can have a sequence of elements. And then you can grab a particular element by specifying the index number. Index number starts with 01. If we change it to, let's say, three, it would print 1234. You can also grab the last element by specifying minus1. And minus two would give us second last element. In Python, either single quotes or double quotes would work. And you can have single courts within double quotes are double-quotes within single quote. Let's concatenate string one and string two and print it out. Let's start looking at loops. We've already seen an example of a flu. So you write e flew four like this. If three is less than four colon, then print. We didn't a fluke. And wherever indentation edge loop ends, we'll print out say the flu, Please less than four. So it printed book. You can also put a parentheses here. If we make, let say three greater than four, it will not print this lane. There are many ways you can date for looping by Tn. There is something called range. You can break for i in range five. Value of high value of phi. Let's do that. Range. We can give a comma. If I was is clean, we could have concatenated. But this is another way of predicting values. By ten. That is something called string interpolation. You can write the value of I0, then curly braces, and then you can say dark format. So that this value will get bust. So that you can have this. Or if there is a string you can just concatenate then printed with mainstream. You can also have a for loop to loop through a list. Let's declare another list, L2. Now to look through this, you write for j mindless to bring value of j. Let's run it. Bring value of j within the loop. We've already seen an example of function in Python. Desire declared a function. Let's have another function. We call it calculates sum and take two parameters, a, b and return a plus b. Now we didn't the main method, we'll call this calculate some 5-6. Let's store it in another variable. To equal this will print it out. There is a cutout. Calculate sum is not defined, will fix this typo. You got 11. We can also return multiple values, let say sum and multiplication. Both. The way to do that is we take comma, you can specify what all things you want to return. Now we're returning a plus b and multiplied by me. And we can store it in two variables, three, by declaring them like this. Then 23, and then print wherefore. We got the, we got 200 suitable to return two values from a function in Python. To write data to a file. You simply do with open. Give the file name and mortis w, that is trade. And then break. Let's execute this. My failed one got created, let's check it out. Sample content one has been populated. We tend to append mode. You can append more content. So discontent appended to the artisanal content. You can have w rate model. Let's contend with new content. So the content got overwritten. 6. Python dictionary: Let's now understand an important Python data type called dictionary. Let's create a new project and name it as my project 2. Will open it in a new window. Let's delete these commands. Will run it to make sure everything is okay. It runs fine. Let's now declared a variable in which will store dictionary data. The variable name would be my course. A dictionary stores key-value pairs. Let's declare key for each course and then also a good name for the corresponding key. Bulimic key called BD. And the corresponding name of the course would be a big Data Hadoop Spark project. Then we can put a command art more keys. Let's have another one called ML. And the course name would be machine learning model deployment. We'll add one more. Let's call it java. And course name is a Java Spring Boot microservices project. Now let's print value of a key. The way to do that is you specify the key name within square bracket. We can see that Java course name is getting printed. So key and value can be either in single quote or double quote. We can print the entire dictionary. It would print all the keys and the values. We can Arctic key to the dictionary by giving the dictionary name and the key name in the square bracket and the corresponding value after the equal sign. Let's add a new key called Spark, and the value would be pi. Spark coding framework will print the dictionary. After adding this key. We can see that the new key and the value has been added. You can use the same syntax to update a key. Also, if the key already exists, it will update the value. Let's change the value of sparky to something else. We'll call it sparks color-coding framework. Syntax wise, it's same as adding a key. Now if we print it again, first we'll see the old value, and then after that, we'll see the updated value. To delete a key, use the del keyword and then specify a dictionary and the key name. Let's delete ML. And after deleting will print the dictionary again. We can see that the milky has been deleted, has shown in that last print statement. Let's now try to print the value of a key which doesn't exist. We got an error that is key error. It says CMS key doesn't exist. We can avert this error by using the dot get method of the dictionary. Simply say dot get and specify any key name. If the key doesn't exist, it would return null. It would not throw an error. Let's run it and see the stems are program exited with code. That is success score. And we can see that none is getting printed. None is also false in Python. We can use that to write a conditional block. Let's store this value in a, another variable. We'll name it as course exist. And if course exist, that means if it is not none, then we'll print the value, of course exist. If it is none, it would enter the else block and there will print. Course doesn't exist. We can put any string here. So now it printed course doesn't exist. And if we specify key that exists, for example, Spark, then it would enter the if block and it will print the course name. So this is how you can do programming using dictionary. 7. Python List and Tuple: We'll now look at another Python collection data type called tuples and see how it is different from list. Let's create a new project. We'll call it python collections. Let's declare a list. Again. We'll have four elements and let's print the list. We can also print specific elements by giving the index number in square bracket. At index 2, we have three that got printed. Now let's declare a tuple. In Python, we have something called tuple, which can also store a sequence of elements. Those elements are captured within parenthesis. And let's print the tuple. Will also print one of the elements from the tuple. It works pretty much the same way as the list, but there is one key difference. Tuples are immutable. We can add more elements to the list. For example, we can say my list append five. It got added at the end, printed. Now let's try to do the same thing to the tuple. There is no R-dot append method. We cannot modify a couple. So tuples are immutable. We can remove an element from a list by using the pop method. Let's simply do pop and it will remove the last element. We can also do pop and specify an illuminated a particular index. For example, let's delete the element which is at the second index, that is 2. Second index is one. Index number starts with 0. We can see that two Guard remote. We cannot remove an element from a couple. So tuples are immutable. 8. Organizing code with Objects and Methods: From here on, we'll dive into more real-world programming. We'll build a Python module to ingest data from a file, do some processing, and then persist our data to a data store. We live it driver program, which we'll first invoke the in this module to justify. And then the driver program would call the module, parses the file. While building this framework, we would learn how to structure the code, how to create classes, how to call one Python file from another file, and various other concepts. So let's see that in action. Let's go to PyCharm and create a new project. We'll name it as file processor. Will open it in this window. And let's first get rid of all the commits. You can right-click on a file and do Refactor Rename. When you refactor by each n will automatically update the file level at all the places where the file is getting used. Let's call it driver dot-dot-dot. We'll just run it to make sure everything is okay. Right, so this runs fine. Let's add a simple print statement at the top of the program. And let's run it and see what happens. If we can see here the fast lane got printed and then by jab got printed. When a Python program starts, it executes all the core that is outside of any method, including the main method. So it'll execute this first and then call the main method. And then whatever code is getting executed from the main method that will get executed. We can also run a Python program without any method. Let's delete this and run it again. This will also run fine. We'll open a command prompt. We'll go to this directory. From a command prompt will execute it by saying Python driver dot py. So this is how you will execute Python in any Linux environment or in any production environment. It takes you go to this link. Now let's add this main method and the other method, and we'll also have a print statement here. Good. First printed the line which is outside all the methods, then it printed entering the main method, then it printed the print statement, which is within the print method. If we run it from here, we'll also get the same output. This is our Python program gets executed. We can also do object-oriented programming in Python. We can create a class and write functions within that. So let's see how that works. Let's create a class called driver program. And within that will create functions. We'll have a function, let's say my function. By default, all class level methods take self as a parameter. Self represents instance of the class. And using self, we can extract all class-level variables. We'll see that in example shortly. Let's have a simple print statement for now. Inside my function. Now the way to invoke this function is by first instantiating the class, then calling my function method. Let's see how that will work. We'll instantiate the class driver program. Let's have an object called driver. And the way to instantiate classes by giving the class name and then parentheses, which will invoke the default initializer or constructor, will come to that in a bit. Now once you have a driver object, we can call the main function. So though this takes self as a parameter, we do not need to write self here. But if you have more parameters, then we can specify them here. We'll see many examples of that. Let's first run it. And you can see the sequence of execution here. This is my driver program, which is the first line in the Python program that got executed. Then it entered the main method. It executed a function which is outside the class. So you can have functions, our save the class and within the class in the same Python program. After that, we instantiated the driver class and call dot driver class. My function will learn more about class-level functions and constructors in the subsequent labs. For now, Let's add two more Python files and invoke them from the driver program. Let's create a class for it. We call it FileReader. And let's have a function called read file. We'll have a simple print statement for now. Let's click another button file. It parses start by. And we'll use this Python program to store data to Postgres table. Later. We'll create a class. Let's call it parses data, and declared a function called store data. And we'll have a simple print statement for now storing data. Now the investor and persisters, they're in the same directory is driver dot py. We'll create an instance for the FileReader class. Let's call it ingest. File reader will not be visible to this Python program unless we import though in distort by file. The way to import a Python file is by just giving the Python filename import ingest, and then we'll also import persist. Now we can say in just dot FileReader and instantiate the class. Let's change the object name to reader. Let's also create an object lighter for the class. Now we can say reader read file. Then we can say writer datastore data. Let's now geocoded. So it executed the code that we had written earlier. Now it also created an instance of the FileReader and instance of the purchase data class. And then it invoke the methods. This is how you can structure your code using different Python files and classes and functions. We'll keep announcing this application in subsequent labs and build an end-to-end application per processing file and storing the output data. 9. Initializing variables with Python constructor: In the previous lab, we created the basic structure of our Python application for processing files. We created three different Python files, and we also created classes and instantiated them and invoke functions within those classes. Let's now understand an important concept called constructors. Using constructors, we can essentially class-level variables. So in the driver that by way of a driver program, and when we instantiate this class, by default, the default constructor gets invoked. We did not have to rate the default constructor when we are seeing Dr. program. And then parenthesis, it's calling a default constructor. Let's see how that looks. As soon as you type def init PyCharm auto-completes the default constructor. We can have a simple print statement here. Let's run the program. And you can see that I am within the constructor is getting invoked. We did not have to call the init method explicitly. When we instantiate the class, the constructor gets called. Now let's understand how to define class-level variables and use it throughout the class. We'll be using the file processing framework to process different kinds of files while instantiating the driver program will pass file type is an argument, will have a class level variable, file type, which will store the file type getting past when the constructor is getting invoked. And let's pass the file type here. Will pass CSV file tape and then store that to the class level variable file type. Now, we did the main function. We can determine which files that we need to process by using the class level variable. We can say you're processing. And then self.age file type, processing, file type. And then finally, let's run and see what happens. So we can see that the file type CSV got past and got assigned to a class level variable. The way to his any class level variable is by using self. And then we can use it anywhere in the class. All the function of the class will have access to this. We'll now move this code to the function within the driver program. Because from men will invoke the driver and then driver would subsequently invoke other fight and files. And wild calling FileReader will pass file type as a parameter. And let's modify FileReader to take that parameter. We live as similar Cortes David program will run the driver again. Firstly printed this within the driver program. Then it entered the FileReader constructor. After that it printed the reading a CSV file which is within the file reader read file function. And finally, it invokes storing data. Now when it comes to storing data, would be storing data in a Postgres table. So we'll specify that type here. First. Let's declare a constructor here. And we'll take BB type as a parameter. Let's have a print statement here and then self.age, BB type as DBT. And we'll say storing data to whatever is the DBT. Now within the driver program will pass to our database type. Let's pass Postgres. We can see that storing data to Postgres is getting printed within the purchase dot-dot-dot. And we can also see the print statement within the parses data constructor. So this is how you can use constructors in Python to initialize class level variables. 10. Logging using basic config: Let's now understand how to use logging in Python. Till now we have been using print statement. In the real-world, you'll be using Python logging framework or some other logging framework so that you can control the log level at runtime. So let's understand how that works. First, we need to import the logging libraries that is available in Python. Logging is various methods using which you can print log. Let's write login dot debug. This is a debug message. This is an info message. And then logging dot-dot-dot, wanting for wanting misses. And we also have something called data. Now let's run this and see how this works. We can see that the wanting bases in the edit Mrs. got printed. However, the debug and in four did not get printed. So by default, the logging level in Python is wanting and anything higher than wanting gets printed. So let's see how to set the log level. To do that, we can invoke the basic config method and then specify the level here. Let's specify the level is info. Now once we do that, info and anything higher than that would get printed, Let's run it again and see the output. We need to write it in capital. Now we can see that info, warning and error are getting printed. And if you want to print debug, we can set the log level to debug also. Now all four are getting printed. So this is how we can use Python logging libraries. And instead of print statement, we can have log statements and then control various log levels depending on our requirement. Typically in a production environment you would print only wanting an error. But if you encounter any issues, then you would set the log level to debugger in fought to get more information from the application. Now let's replace print statements with this. Log statements. Will move this to a class level variable. Let's remove the log statements from the main method. And within the class wherever we have print, we'll replace that with logging dot debug. Let's run and see the output. Now we can see that the debug statements are getting printed. It hired log level, like in for wanting, then this will not get printed. Now as you can see, the debug statements are not getting printed. We could do the same thing within other classes also. Let's import logging here. We got an error, let's check it out. We need to write it in small letters. None of the debug statements are getting printed because you have set it to wanting. If we change it to debug, then the debug statement should get printed. One thing to note here is though we changed only for the FileReader. It is also printing the debug statements within the driver class. This is because we have the same logger, that is the root logger in all the classes. In the next lab, we'll understand how to read logging configuration from a property file and how to have different logging levels in different classes. 11. Logging using file config: Let's now understand how to control the log level through a config file. It will create a directory called resources. Under that will keep all kind of resources including dot config file. Let's create another directory under Resources called conflicts and the under config file called login.com. First, we need to define the type of loggers. We'll start with root logger that we'll be using. The entire application. Subsequently will have different loggers for each apart python files next to it. To declare a handler. With handler, we can send output to either console or to e-mail or to some other channel. Trying out Console handler. Can this lab. Next we need to specify that route logger will be using the console handler. And to do that, we need to declare a property called Logger underscore root and then declared the handler. We can also specify the log level here. It could be debugging for error are running. Next we need to have a property called handler underscore console handler. And within that, we need to have a formatter. We also need to declare a formatter underscore sample formatter property, and then define in what format the log will get printed. We also need to define the format is a property here and specify the keys is humbled for murder. We'll go to the main application. Let's now understand how to use the property filing the logging framework. First we need to import logging dot config. Then instead of using the basic config, we'll use the config from the configuration file that we just created. And to do that we'll say login dot config, dot file config, and then specify the file path which would be related to the root directory. It would be slash resources, slash conflicts. The file name, which is login.com. And we can get rid of it. Let's same thing in other classes. Now we'll run it and see if it works fine. We also need to import logging dot config in, in just dot py and persistent by. Let's do that. We've got a key error that formatter doesn't exist. Let's check it out. We need to remove the slash here. It should be relative directory starting from the root directory, nurture, done fine. Make sure you do that in all the classes. Now we can see that nothing is getting printed. So let's understand how to control the log level here. The root login is defined as debug. That is getting overwritten by the console handler will set this to debug also and run it again. Now you can see that all the debug statements are getting printed. You have a root log level. And for each of your handler, you also have a log level which overweights third root log level. Let's put one in here and see what happens. Now nothing is getting printed, though. Handler overwrites the root log level. In this case, root is wanting log level which is higher than the debug log level set in the console handler. So that would take precedence. Let's change this to debug. And then we can control the logging level of the application using the console handler. This one, Let's set it to info. Now, anything higher than in Ford get printed. And we'll keep this debug for now so that we can see all the log statements. So this is how you can control logging level three configuration file. Now we used route logger for the entire application. In the next lab, we'll understand how to have different loggers for each of our Python files. 12. Having multiple loggers in an application: In the previous slide, we saw how to control the logging using a config file. Next, we'll understand how to have different error level four different modules. For example, if we get some error in the production environment for the parses module, we can increase the energy level for the module without increasing log for that application. So let's see that in action. Now let's declare to more than loggers. One is ingest and the other is persist. Similar to the root logger will have properties for ingest and persist. Next, we need to define the name property using which you can get a 100 to the logger. Let's have a qual named ingest for the ingest logger. And a filename persist for the Persist logs. Let's keep a log level for all the loggers. Now let's see how to use this. Specific loggers will go to ingested by. Now after reading the config file, we'll declare a variable logger. And then we'll get the logo from the, from the logging get logger function using the column name. Now instead of logging dot info, we need to have Blogger dot info because that is the object we have within just login. Let's do similar change in the person class. Here we'll get lager persist. Let's now run it. Logger is a class level variable. So to use it in other functions will have to say self dot logger. Let's do the same change in ingested by now the program runs fine. So let's now understand how to control error level in different modules. We'll go to login dot conf and will suppress log from all the modules except parses module. We'll set this to info, will keep the root test debug. But in the ingest model we live info. So in this law will get printed, but persistence debug, so that should get printed. We can see that the info statement within the login model is getting printed. And it is getting printed twice, so we'll come to that in a bit. But the debug statement is not getting printed. Let's say that the log level to wanting in ingest. Now we can see that all the log statements within the ingest module that design within the file reader, reading a file, those had been suppressed. One thing you have noticed here is the debug statements are getting printed twice because by default it picks up that route logger can also the logger that is defined in a specific logger. Persister ingest to ensure law gets printed only once there is a property called propogate, we can set that to 0. So that would ensure that log is getting printed only once. 13. Error Handling with try except and raise: Let's understand how to do error handling in Python. We'll implement error handling within the persist module in the file processing application. In Python to catch error in code, you can put the coordinate try-block. Let's create it try block within the stored data function and put the code within the try block. Next, we'll define an except block where will tell the program what to do if an error occurs within the try-block. Let's have a simple log statement. And this time we can use lower.tail here so that it will always get printed. Let's put some text in error has occurred. Also, along with the except statement, you need to specify what exception you are expecting. Let's have excepts and four now, which will catch all kinds of exceptions. And we can print that to the log and to print the error to the console, we need to make sure it's in string format. So we will convert the exception to a string and print it. Now let's run it here. Integrate exception as EXP. Now everything runs fine because this doesn't throw an exception. Let's have a variable, var one and have a value a 100 divided by g. This should throw an error or exception which should get caught within the except block. We can see that the program entered the except block and printed there. There are the exception in this case is division by 0 because we're trying to divide 100 by 0. Let's try to do the same thing. Try-block. We can see that the program exited with exit code one. We got the same except some division by 0. But because it was outside the try-block, you did not get caught within the except block. So the program throws an error and exit it. So it's always a best practice to use try and except block within Python. If you think your code is likely to throw any error, then your program will handle the error and I got exit gracefully or continue the execution of the flow. After stored data, I feel in the other function invocation that would continue, but your program would not stop if there is an error within the stored data function. 14. Reading configuration from properties file: Let's now understand how to read properties from a config file. In the previous labs, we saw how to read logging parameters from a config file. But in a real-world application, there'll be several other properties other than the logging properties that you might want to store in the properties file and breathe at runtime. The advantage of a configured properly fail is if the value change, then you do not have to modify the code. You can just modify the values in the property or the config file. So let's understand that clean example. Under the Resources folder will create a property file. In Python, you create a property file with INA extensive, let's call it File Processor dot ionize. Within this property file, we can have different sections for different types of properties. Let's have a section for database conflicts. Under that will have a property called PZ table, which transport Postgres table. Later on we'll use this table in the code. For now let's understand how to read this property from the properties file. Will have future x-dot courts table. Puja next is the schema and coach table is the table name. Let's declare this and now let's read this value in the code. We'll go to persist dot py. First we need to import the conflict parser. Instantiate an object, config using the conflict parser class available in the conflict parser liability configured the read method using which we can read a particular property file. We need to specify the path relative to the root directory. What's single quarter in double-quotes would work here. Next, using config will face that table name and stored it in a target table variable. Configures a getMethod. It takes 67. And the property name is parameters, you know, disrupted by which section and which property. So we have a section called database conflicts. Let's declare that here. And then the property name is busy table. And let's try and adopt print statement. Self.age, Blogger dot debug. Target, table name is. We'll concatenate this. Now let's run it. We can see that the table name is getting rid from the property file. Hey key, which doesn't take just let's change it to PC W2 and run it. So there are got printed in the except block, no ops and for p z table 2 in database conflicts. So this is how you can store different properties in a property file in Python and use it in your application. 15. Installing PostgreSQL: Let's download it and install Postgres equal. Go to post-classic collapse eight and go to the download link. I'll be downloading for Windows. Click on download the installer. Let's pick 10 dot 14. I will download for Windows 64-bit. Once downloaded, click on the installer. Click Next. You can leave the default directory. No need for stock below. Will give our admin. Admin, you can choose any password. 5, 4, 3, 2 is the default port. Let's install. Suppose this sequence has been installed. To Lord post-classic will simply take BCR and click on it. Bcr administer interface to a database. It opens it in localhost port phi 1, 4, 0, 1. If PCR, when takes time to Lord search where PC quill, which should also be present on your machine. That is the command-line tool to Enter postgres. When prompted for local laws just hit Enter on database or default database postgres hit Enter. What is 542, that's 34 port. And the username which Postgres password for the user positivists. So that is the password that you would have given during installation. I gave Arduino, so I'll enter that. And now I am in the Postgres database. Let me clear this schema, create schema, future R6 schema. Makes sure you have the semicolon up terribly DDL SQL statement. I'll create a schema, schema and then magically the table schema, dark future Next underscore course catalog. But w lab, six fields edge described here. So the table got created successfully. Let's insert some records to this course catalog pebble. This table lays course ID, course name, course 67, and creation date, where inserting a row with course I did two course name Hadoop Spark hotter as future skill, and this is the core sex. And in a JSON format, we specified the core section type education or course name. It is varchar character waiting, which is like stream course ID's integer and not null. Clear some date is date which is not null. And we've added a constraint dot-dot-dot. Course ID is the primary key. Let's hit Enter. We do not enter the schema name correctly. Let's do that. Insert another row. Now we have entered two rows. Let's select data from this table. We can see that we have a futuristic schema course catalog table. And within that we have two records. So this is how we can install Postgres and create Schema, create table, and use this database for your application development. 16. Reading from and writing to Postgres: Let's now interact with the Postgres table that we created in the lab. To interact with Postgres from Python, we'll use the psycopg2 library. First, we need to import that. If we're working on this library for the first time, you need to include it in the Python environment. Let's go to File Settings. Under the project, we need to select the Python interpreter. Then we need to make sure psycopg2 is installed and a peering under the list of libraries or packages here. Since I've already installed it is showing up here to install psycopg2 or any library. You click on this plus sign. Search for the package you want to install. Then select the package and click Install package. If we're working in any other Python environment, you can do a pip install to install psycopg2. Let's close. This will create a new function. Let's call it read from PZ. First, we need to create a connection with a Postgres table. Psycopg2 has a connect method using which you can connect with the Postgres database. You need to specify the user ID, which is Postgres, in my case, the password, host name. Since I've installed on the local machine, it would be localhost and the database name which I kept Postgres, or the default database. Now we need to store this in a connection variable. Let's wrap it so that it could be visible in the window. Now after establishing the connection, we need to create a cursor. Using the cursor, you can execute various Postgres command within our Python program. You can create all kinds of queries such as select, insert, and delete. Let's try a simple select query. Will select all records from the future schema, future ex course catalog table, which we created in the other lab. Let's first execute this query in the SQL command prompt. We can see that two records are getting fetched. Coursera has an execute method to execute any query. Let's execute the select query. And once it is executed, we can fit a single record or we can fetch all the records. Let's fit a single record. Eugene cursors fh one with third and printed to the console. Next we'll invoke this read from PZ from store data function so that it will be executed when we run the entire application. We have to do a self dot read from PC since it is a class level function. Let's run it. We can see that one record is getting displayed here. The record width courts ID 2. First we established a connection, then we created a cursor, and then using the core Selleck g could be executed the query. And then using coarser dot-dot-dot H1, we are fetching one card. We can also fetch all the records. We can fetch all records using card self.age all. Let's print output. We can see that two records got phage trend getting displayed here. The output is within a square bracket, so that means it's a Python list. When we do a cursor dot dot H on, it returns all the records and stores each recording that tuple, a list for all the records. In check the psycopg2 documentation to understand all the functions are interfaces available and the cursor object and what kind of data type the return phage all returns, all the rows in a list of tuples. And an empty list is written if there is no match to the records faced. We can store the feature loud put in a Python list and iterate through it in a for loop. Let's call that list records. And then for each item in the records, let's print item and we'll print something else. Also within the for loop. We can see the expected output, printing each record and then printing the text within the for loop. Let's understand how to insert a record to Postgres will create another function. Let's call it right to PZ. Similar to read from PC will create a connection and then create a cursor. Two-part form insert operation with coarser, we need to write the insert query with values and have a tuple which will populate those values at runtime. When new course ID, course name and other details. Next, we can perform the insert operation by calling card self.age equals method. This time we have to pass the insert query and the tuple. Finally, we have to close the cursor and commit the connection. Let's do the same thing in the read from PC method also, it's a best practice to commit the connection and close the cursor after every database operations. Now we have two methods. One reads from Postgres and one rage to Postgres. Let's invoke rate to Postgres first. Before invoking that read from. We'll do self dot right to PC. Let's have a print statement within the right to PZ function. Let's now run it to see the output. We can see that one the court got inserted. And it's displaying three total records. We can also find a select query in the SQL command prompt to see all the three records. So we hard coded the table name in both the queries and we habitat two places. So instead of that, let's move the table name to the property file that we created earlier. We'll store this table limit the property file and we'll retrieve it using the PC table key under the database config section, which we are already doing in the code. Let's go back to the code. We are storing the table name in a variable called target table. We'll pass it as a parameter to both the functions and modify the query to read it from the method parameter. So this is what the select query. Let's do the same change for the insert query. Before running the program will change the new course key to a different value. So that will not get unique key constraint era. And we'll have a different course name and run the program again. Let's check this out. We forgot to add a plus sign here. Let's fix it. This time we got another error. It says missing one required positional argument. Though we added target table to both the functions. But while invoking, we have not specified that additional parameter. Let's fix that and run it again. This time it ran fine with the exit code 0. Should this is how you can make your application configurable. In future referred table empty and this all you could do is modify it. We did the property file. You do not have to modify the code. 17. Organizing code further: Earlier we saw how to import ingestion persist modules within the driver program. Now we'll create a subdirectory and store this ingestion persist file. And let's see what happens. We'll call it processor. Now let's move ingest and perceived or pipe to that directory. Ihm prompts for refactoring. Let's do that. Now when we click on driver that we can see the import statement has been changed to from processor import, persist or ingest. Earlier when the files within the same directory, we're importing them by just giving the file name without the extension. But now that they've been moved with subdirectory, we have to do from processor import persist. That is the way to import files from another directory. Let's run it to see if everything is okay. Now persistent in just models are not finding the login config file, and they would also not find the file processor IANA. Let's move the entire resources directory under the processor folder. And we'll refactor again. Now we didn't the driver login.com is getting exist with relative directory starting from the root directory. And if we go to index.php, there we would see relative directory starting from the processor directory. Let's see if it runs fine or not. We again got the same error. Now let's hard processor directory here also will do the same change we didn't purchase dot py. Now wherever we have locked veiled reference, the relative path from the project root directory should be used. We'll run it now. Logging error has gone away, but we are seeing an error that data is fixed doesn't exist. So let's update the directory name for the INI file also. So we've changed it in parses dot py. That is the only place where it is getting referred, will run now. Now the program, given that the unique key violation happened. So let's fix that. We would have a different key for our course. So this time it ran find these or we can organize your code further. You can have all your Python files in the source file under one directory so that you can easily package it in, take it to another environment. 18. Handling the unique key constraint error: Let's now check how to handle the unique key constraint error that we are getting every time we run this program, we are inserting a record to the course catalog table with the course ID, which is hard-coded in the program. There are multiple ways to handle it. One of the easy ways is to take the max course ID then incremented by one and the new SSID to insert a new record. Let's see how it can be done. Before inserting a record, we can execute the select query to get the max course ID. And after that, we can do a fetch one, which would return us one row. So in this case, the select query is going to return only one row and that would get returned. And that would be in a tuple. And to extract the value, we can get the first element of the tuple. Let's store it in a variable called max course ID. We'll print that value. And while inserting a record, instead of hard-coding, will say max course ID plus 1. Let's run it and see what happens. It says cannot concatenate integer to string. So while printing, we need to convert this max course ID, which is an integer to string. We'll run it again. Now it runs fine. And a new course ID 7 has been inserted. If we run it again. Another record with course 88 is when inserted. So this is one way to handle the unique key constraint data while inserting records to a database table. 19. Reading data from a JSON: Let's now see how to read data from a file. And later on, we'll use that data to insert into the database table. Will go to JSON editor online. Upper typing the JSON string in the Code tab, you click on the three tab. If everything is fine, it would load correctly. But if there are any errors, for example, if I put a single quote here, it shows an error here. If we click on tree, it would not load. Json is a popular way to access data in the real world. And we would be storing the course information in a JSON file and reading it from there. And later, we'll use this data to insert into the database table. Let's copy this. Within PyCharm. Let's create a new JSON file under the root directory called cornstarch JSON. Now we'll go to index.php. Can read that JSON file. To work with JSON files in Python, you need to first import that JSON package. Simply do importation fast duty to read the content of the file. And you can read that the way you read content from any text file. With open, then the filename that is courts dot JSON. Now let's declare a variable called new course, and we'll simply say JSON.org if we need to convert the JSON string before printing. Now we can see new courses getting printed here. It is reading the content from the JSON file that we just created and displayed in the console. Now let's make a few other changes. Will change the file type is JSON here. Whatever JSON string we are creating will return that. From here. Let's have a variable grade Jason. And we'll populate God, return value in that variable. Let's print it here also. It runs fine. And we can see that it is getting displayed in the driver program. Next, we'll understand how to insert this JSON string to the course catalog pebble. 20. Writing JSON file data to PostgreSQL: In the previous lab, we read course information from a JSON file. Now let's understand how to insert that data into the Postgres table. We have their data populated in the Read JSON variable. And within the sys.path will create a new method. Let's call it right from JSON to PZ. And we'll create a connection. Create a cursor. Apart from target table will also take JSON is a parameter. Let's call it course Jason will have an insert query is before. We'll also declared a tuple. This time instead of hard-coding, the course information will extract the values from the course. Jason will say course Jason. And we didn't bracket course name. It has to match with what is their invalidation file. Next, we love our third name. And we'll have core XN and cleared that. We also need the max course ID here. Finally, we'll execute the query and commit the connection. Let's now call this function from the store data function. We'll comment out the other two function invocation court. We need to pass the target table. And courts JSON. There are two ways you can pass the courses and from the driver program, either while calling the stored data method as an additional parameter or we can put it in the constructor code. Let's pass it as an additional parameter. Will go to a driver dot-dot-dot. And whatever Jason we are reading will pass that as a parameter. Let's have a print statement before we executed. Now let's run it and see the output. It says course NameNode defined. We need to put this JSON attributes within quotes. Now we got a different error while inserting to the caudate failed because core sections adjacent type and we're trying to insert a blank string. We can either convert this blank screen to JSON format or glitz Article Six 100 and JSON format. And then use that to insert the record. Let's go to JSON editor on lane and four core 67. Instead of having a blank value, we'll have another JSON. So you'll have a JSON within the Qishan. Now we'll use that JSON in our program. Now we got to mirror that, counted up the type dictionary. So within the parses dot py, we're reading the course section. Let's print the value of course section. The core six and is getting laid correctly. However, is getting treated as a dictionary, not as a JSON object, which our database field is expecting. To solve this issue. We can convert this to addition. Let's import JSON here. Now instead of saying core 67, now we'll say json.dumps, which will convert this to a JSON object and pass it to the database query. Let's see that. Now it got inserted correctly. Let's query the database to find out. We can see a new entry with the name new course and the course 600 details that we just entered. Let's modify the value and try again. You've got executed successfully, will create the table again. We can see the new entry is that we can read data from a JSON file to Python program and then use that to insert to a database table. 21. What is REST?: In the next few lab, we'll be building rest web service using Python. So let's understand what is service or web service in the internet world? Web service is a software that makes itself available over the Internet. A web service can be accessed over HTTP, FTP, and many other protocols. Typically digitizer extends in XML or JSON format. Now, in the real-world, you'll see many examples of web service. For example, in the airline might exported stickers availability status to a travel portal through web service. It doesn't need to give the travel portal direct taxes to its database. Race is a popular way of accessing web service, restaurants per representative state transport using wrist, you can access the web service and access data in XML or JSON format. Json format is more widely used. There's some contents key-value pair. Any application which wants to extract data from a web service can get a JSON response and directly read that response or convert that to a class and object and then read the response. 22. Understanding how REST will be used in the application: Till now we have built a Python application which can store some data in a database. And we have also built a module which can read data from that database. Let's now understand how we can give people access to read and write from this database without giving them all the database credentials or access to our Python modules. We just learned about rest web service. Using rest, we can create different endpoints through which people can read or write data from our application. Using race to exchange data over HTTP protocol. You can specify what is the method type for your rest API. In this course, we'll learn about HTTP methods, GET and post. If we are using GET method, the requested parameters will be sent in the URL, where it's what post method the parameters get sent in the request body, which makes it more secure. Let's dive in and build their HTPS. What are Python application? 23. Creating a REST API to fetch course list: Let's now understand how to create a rest endpoint to retrieve all the course information. Python is a popular web framework called Flask, using which we can easily build rest EPA's. Let's see how that works. First, we need to import Flask and request object. We need to ensure flask is added to the Python interpreter. Let's go to File Settings. We'll click on the plus sign here and select flask and install. Flask got installed successfully. Let's close this. Now the error has gone away. Now to create a flask endpoint, we first need to create an app. Then using app, we need to define the end points. Let's first have a gated point using which will retrieve all the course information. Will declared slash courses, which will then point the URI to get course information. And the meter type would be good. Let's have a method. Courses. Good courses will be mapped to the last courses you array. The function name doesn't matter as long as it is defined after the approved definition. It will get triggered when slash courses you are releasing book. Here we can create a new method or we can connect to parses don't buy read from PC to get the course information will create a new object, db object. This will be an instance of dog persist data class. Will invoke read from PC function of db object. To get this information. Let's go to that function. And are they return statement to return the records. Back in the graduate program will store the return value GenEd courses variable. Next we'll return the courses to the client, invoking this APA. Let's append some text to it. Courses are, and then the courses variable, which will have all the courses. Next, let's make some changes to the main function. Will commend the old code. And we'll simply say Update run that would start the up. At a particular port. I have defined a 1000 five, but you can have any port here. When the program starts. This will launch a Flask app. It port in 2005. And it would expose an endpoint using which all the course information can be retrieved. Let's run this. The app is started. We can see a misses that it's running it. Localhost 8,500, 2700, 0, 1 maps to the local IP of this machine. Let's go to a browser. We need to put slash courses here. And we got an error that missing one required positional argument target table. This method expects that target table. Let's simply hard-coded for now. We'll stop and read on it. It's running again at 48000 five. Let's refresh the page. It says cannot concatenate lists to screen. Python is dynamically typed. Many typewriters will not be known until the program is executed. It will convert the courses to stream before returning. It will stop and read on it. It is again running at port 8,005. Now we can see that the course information is getting phased. We can also make a rest call using the postman. Let's search what Postman tool installation. Download the right version for your operating system. Once downloaded, click on the EXE to install Postman, then magically get loaded. You can sign up using your Gmail ID. Let's open Postman again. Now let's create a new request. In Postman, we need to capture the URL and specify the request tape. Let's capture the URL up dab that we just launched in the local environment and change the request tape to get click Send. We can see the output here. We can also create a risk gland to face this information. Let's create a new project. We'll call it risk gland. Let's get rid of all this code. We need to import requests. Then let's declare the URL and we'll point it to the court says endpoint that we just created. We need to make sure request is important. Using requests package we can send and receive HTTP request. We need to ensure that is added to the Python environment. Let's go to File Settings. In the Python interpreter. Let's are the requests. Will select it and say install. Your day's been installed successfully. Let's close this. Now that error has gone away. Next, we'll invoke the rest service using requests dot get. And we'll specify the URL. And whatever response we get, we'll print that. Let's run it. We got a response to a 100. So that means it's able to access it. Now we'll do a response dot txt to print the contents. We can see that the course information is getting face can getting displayed here. So this though, we can create a rest endpoint and expose your course information to the outside world. You do not need to give people direct access to a database. They can just hit the URL and retrieve all the courses. 24. Creating a REST API to store course information: In the previous lab, we created a risk and point using which we can fetch all the course information. Now let's create a rest endpoint using which we can post course information or insert course information to the course catalog. Let's create another end point called course. And this time we'll be sending data to the method table needs to be post. Let's have a function called Insert course. We have a function in the sys.path which reads a JSON object and inserts that to the database table. Let's use that for this demo. We'll first create a db object for the parses data class. Next we'll invoke right from JSON to PG function to insert data. It takes core stable and JSON as a parameter. Now when a user is interacting with this endpoint, the eugenics to post the JSON object in the request. And that'll be red here and the JSON string would be extracted. So let's see how that would work. Now using request dot get JSON, we can read the data and store it in a local variable. Let's also print it and see the output for our reference. So we'll read the JSON in past 30 days onto this function to store it in a database table. Let's stop and start it again. So now we have two endpoints exposed. One is to retrieve course information, and one is to store course information. Let's go to Postman and hit Send. This still works fine. Now we'll invoke the course you are in and change the request tape to post. And we also need to send the course JSON in the body. Let's copy it from the JSON file that we created earlier. Will change the values. And let's post it. We got an error, let's check it out. We did not have a return statement here, simply return success. And we'll stop and started. It's running again. We'll go to Postman and submit this request again. And we got success. Let's see if this new course got inserted. We can go to the history and get-go old request information from Postman here. We'll send a get request again. The course that we just inserted, it's showing off here. We can also verify the same in the database. Let's send another one. We'll call it new course six. Let's send it and go to the database and query it is showing up here. So this is how you can create an endpoint using which user can post the course information to your application. Earlier we created an endpoint to retrieve course information. Let's now see how to interact with the coarse endpoint to post-course information from a Python program. Let's declare a new variable called posterior. And now instead of saying request dot gate, will do request dot post. And we'll specify the URL. And we'll specify the course Jason. Now let's have a sample JSON string in the course Jason variable. Now we have this JSON string. Let's use it in the rest client. We need to remove all the extra spaces before we can paste it here. There are various online tools available using which you can remove extra spaces from your JSON string. Let's use code beautify. Simply paste the JSON string here and click Remove, recreate a string without spaces. Let's copy this string and use it in the wrist gland. Now let's create a JSON object from the string, will say json.dumps and then capture the string here. This should convert the string to a JSON object. We also need to import JSON here. Let's change the course name to something else and send the request. We need to have the post URL here. Let's correct the urine. And this time we got success. We can see that the new record has been inserted. So this is how you can send a post request from a Python program. 25. Python unittest package: In the real-world, you'll be unit testing your code before handing it over to the testing team. So let's understand how to do unit testing of Python application using unit disk package is a best practice for each of your Python file. You'll create a separate test violin. For example, what parses dot-dot-dot EU levels the pre-test. Finally, the convincing is to prefix test underscore with whatever file limb and then create that test Python file. Let's create it. Taste for. Sys.path, will create it under the root directory. We'll call it test underscore persist dot py. First we need to import unit test package. Unit test is a Python package or liability using which you can create taste for your Python application. Next unit to create a class. Whatever class you are testing. For example, we will be testing persist data will create a test class appending to the class name. Then within bracket we need to write unit tests, tart taste case. After that, we can create different test cases. For each test case, we need to have a function. Let's create a test called taste underscore first. And whatever function you right here, it has to be prefixed with test underscore. After that, we can write our test within this function. We can write this using the assert functions. Let's start with the assertEquals. Using yesterday qual you can compare two variables or constructs are objects. Let's compare 34. If it is equal when the test would pass, otherwise the test would fail. Now let's run the test. It says the test failed. Now if we compare 33, the taste would pass. Let's write another test using assert true. Then we can write any expression here. For example, if this string is an uppercase, the taste would pass all ready to fail. Let's run it and see it passed. If we write it in small letters, the taste would fail. Also, we need to give each tasted different name. Let's call it second test. So this failed. Correct it. Now we can click here to run all the tests defined under the class. We didn't PyCharm. We can click on this icon to see all the taste in their status. Let's change this and run it again. See that one test failed in one test passed. It also shows you or you can also define a main function. Then right here, unit, they start men. This is another way to execute your test. Let's go to command line and run the test. Will say Python. It would invoke the main function. Let's change this and run it again. And it says one test pass and one failed. 26. Data and error testing: Let's now our taste to one of the functions we created under purchased dot-dot-dot. Let's unit test this function. The idea behind the unit test is we should be able to taste this function without running the entire application. So we need to look at what are the parameters the function is expecting and what is the output parameter. So this function expects the table name and it returns the records. So let's write a test for it. Will remove the taste that we tried earlier. And wherever test to test the read from PZ function. And within that, we can invoke the function and paste if it is working fine or not. First, we need to create an object for the purchase data class. After that, we can invoke the read from PC function, passing the table name. We need to import the purchase dot py here. So from the folder name import, persist. Now if we just run it, it will run fine and the taste would pass. Though we're not doing any S dot here, but you can add a search statement to check the data that is getting returned here. Let's print the first record in courses and see what are the values in that. The first item in the catalog contents Hadoop Spark. If we know that this is not going to change, then we can extract one of these values and do a assertEquals. For example, let's print the second item in this tuple that is at index one. And that should be Hadoop Spark. And then we can write an assert equal here. It would be self.age, assert equal. And then we can compare this with the stream Hadoop Spark. Let's run the test again. So this ran fine. If we change it to something else and rerun. This time the test failed because the comparison fed. This is one way of testing your particular function. But if we know that this course name might change or your catalog might get modified in new Minard, get a Hadoop Spark is the first course, then you cannot have this because in that case your test would fail. Another thing that you could try to seek the length of the tuple, though your catalog might change, but number of elements in a catalog that might not change very frequently. Length of the course tuple gives you number of elements and you can verify whether it matches with the expected number of elements. Let's run it and see the output. So the length, of course, tuple is five. Let's do an assert equal here. We would say assertEquals, length up courts tuple, and then compare that with five. Now our page should pass. Let's run it. We can see that the test passed. Let's write a second test, what this function will call it tastes read from PC2, will give an invalidate the table name. Let's run this test. We got an exception that the table doesn't exist and the error is undefined table. So this is the expected behavior because the table name doesn't exist. Your function might throw all kind of errors. If it is throwing a valid error, then that is expected behavior and you should be able to taste that. You can check for any error using self.age assert ridges. Then you specify the error name which is undefined table. Then we'll call this function here. Also, this error name is not getting recognized. So let's import psycopg2 and will give the package name and also the class name that is psycopg2 errors are different table. Now when we run it, read from P2 through our defined table error, which will be recognized here. And our test would pass. Let's run it. And our test passed. So this is how you can check for different kinds of errors within your Python function. And if the function throws a valid error, then you can make your test pass. Let's now run both artists. In one test. We're doing a data validation. In the other test we are checking if the function is stringer valid or not. 27. Unit testing with PyTest: Let's now understand how to unit test by an application using a popular pest employee. My part by test. We use unit test. Unit test is great verbage. You're looking at a glass demanded that period functions and write your test. Let's understand how this simplifies unit testing. To work with Python. And PyCharm will introduce a few configuration changes. Let's look at them. First, go to File Settings. Click on Python interpreter. Will start by desk. Pecan pie destiny install package. By it is it has been installed successfully. Let's close this. We can see by test here. Let's close this now. Let's go to File Settings again. This time we'll click on Tools. Then click on python integration tools. And under testing will select Default Test traumatized by this. Click Okay. Let's do one last configuration change before we can go to Run it configuration. Click Plus. Click, Test. And working directory would be the project directory. And sclera part would be done. Project directory. Click Apply, and Okay, Let's now create a new Python file. We'll call it dark parses. Do. Now we can write our test functions here. We do not have to create any class in Python installed. So all this should start with test underscore. Let's create a very simple test which would assert the Boolean value true. That means it would always pass. And we'll run this test by right-clicking and saying run by test. We have not important unit test. And now our default test is by test. And the test passed. We can say false and the test would fail. And here it says the assertion error because we're forced it. So it failed. Let's now see how to write a Certainly Colin by test for this or the colored rate is Cr 3. And let's compare it with for this failed. And if we change it to 3D should pass. We earlier wrote some test using unit test. Let's convert them to pilot test for marta. And we'll simply say assert the convention is to rate the expected value. And then like John value, you can date it the other way also, but this is the convention. Even in unit tests, there is the convention. Let's run it now. It says the test fairly secure. Self not found, will remove cell from here. We need to import our persist from processor and port persist. Now the test passed. You can also write and do run by testing, but the test will get executed. Let's now convert the other taste to buy a test. We'll copy this, which checks what an exception. Let's paste it here. Let's remove self will remove cell from here. And we'll import psycopg2. And here we intercept by testdata register for a surpluses European import by this. And then say this.radius, whatever editor you are expecting. And then call the method though we call it unit test. This runs fine. Now we can run all the three test using Python test. All three tests passed as expected.