BS-1 Python basic knowledge-1.10 exception handling and testing

Exception handling and testing

Error type

1. Syntax error
Found only when python is running

Syntax error: syntax error
There is a problem with the spelling of the code. There are more or less symbols
2. Semantic error

The semantic error prompt is not fixed. It depends on the specific English meaning.
3. Logic error
It's not about code, it's about code design. The code does not report errors, but the result is not what you want. Consider the analysis process and whether there is any problem in the program design.

exception handling

Mainly at the code level
Put the possible mistakes in a code block: try, try

Example 1

try to execute code that may cause exception exception exception capture exception

except can capture multiple,

try:
    x = 5 / 0
    print(x)
# Next, we can catch the except ion
# If you don't know what the exception is, write an exception. If you don't write the following types, all exceptions can be intercepted
except: 
     print('Program encountered an error')
# Know what's wrong, write it down
except ZeroDivisionError: # ZeroDivisionError is an exception class that has been written in python framework. The following information is attached to the instance where the exception occurs
    print('Can not divide zero')
except: # If there are other mistakes, they will not be written. They are called other mistakes
    print('Other mistakes')
else:  #No exception was caught in the first two, and an else was added
    print('No exception')

Under normal conditions, the program is executed normally without exception.

Program running exception, exception caught:


ZeroDivisionError is an exception class that has been written in python framework. The specific information of the exception depends on the instance where the exception occurs. You want to know more about the details of the exception

try:
    x = 5 / 0
    print(x)
except ZeroDivisionError as e:  #Catch the exception ZeroDivisionError as a temporary variable. When printing, you can list the error message of the exception itself
    print('Can not divide zero',e) #When printing, the error message of the exception itself is listed. This error display shows that there are both "cannot divide by zero" written by itself and error messages brought by itself, as shown below.
except: # If there are other mistakes, they will not be written. They are called other mistakes
    print('Other mistakes')
else:  #No exception was caught in the first two, and an else was added
    print('No exception')

Error display: there are both self written "cannot divide by zero" and self-contained error messages, showing:

Example 2


AttributeError: attribute error
Make a capture during operation:

# Explanation of the figure above
# Report only errors when AttributeError errors are encountered
except AttributeError: 
    print('Property exception encountered')
# When an AttributeError is encountered, an error will be reported, and then the details of the error instance will be listed
except AttributeError as e: 
    print('Property exception encountered',e)

Example 3

finally

Finally, no matter whether there is an exception or not, the code that we will finally execute is the code, file operation and database operation for the resources that must be released
For example, file operation: to open the file first, read and write the contents. In the process of reading and writing, there is a problem. The file has been opened, and an exception is encountered in the middle. The file is still open, which will affect subsequent operations. In this case, add finally.

f = open('data.txt')

try:   
    f.read()
except:
    print('File operation encountered an error!') #At this time, the file may have been opened, but an error was encountered while reading. At this time, the handle may always be open, and finally is suitable. No matter what, close the file
finally: 
    f.close() # The file cannot be found because it is written in try and forms a local variable. You can write the file outside      

Similar to database operation:
When operating the database data, you just need to open the database, retrieve the data, print it on the console, or output it to a file. In the process, the database has been opened, but it has not been closed during the operation. In this case, you need to close it. So, finally install the code to be executed at the end, no matter with no problem.

raise

If there is an exception in the program, it can't go through like this. It must be handled. If it doesn't, it should also be allowed to run the exception and terminate the program. Sometimes exceptions are thrown manually, raise
console: raise AttributeError('attribute error')

The meaning of this thing:
Similar to an interface, this interface must be implemented. You can write it into a method

def method(): #Leave a location and change the code later. If not, the code will use the default,
    raise NotImplementedError('This method code has not been implemented')
method() #Call him when you come up, that is, use a placeholder to ask others to implement it, and give yourself a raise.

Official python Exception document

Built in exceptions for build in exceptions Python
Website: https://docs.python.org/zh-cn/3/library/exceptions.html ා bltin-exceptions
Website: https://docs.python.org/zh-cn/3/tutorial/errors.html

Code testing

unittest in python
After writing the code, you can test it before execution

Test function

def get_formatted_name(first,last):
    full_name="{} {}".format(first,last)
    return full_name.title() #A method in string title: change the first letter of the string to uppercase

print(get_formatted_name('tom','lee'))

After writing this method, you can write a test case to test whether the method written is correct. You can create a new script and write a separate class for testing.
In actual development, you can create a new folder and put test cases in it.

import unittest #Import unittest module
from main import get_formatted_name
# Write the test case into a class. In unit test module, python has prepared a base class: unittest.testcase
# Write a base class, NameTsetCase test case, and let it inherit a base class from unittest module. The inherited base class is written to the parameter brackets of the class
class NameTsetCase(unittest.TestCase): #Write the test into a method. It is better to define the method starting with test
    def test_title_name(self): #Here's what we need to do: call the method get ﹣ formatted ﹣ name by passing a value to see if the result is what we want
        formatted_name = get_formatted_name # Formatted ABCD name from the called get ABCD formatted ABCD name ('Tom ',' Lee ') method
# How to know whether the test can run smoothly and what is right?
# unittest.TestCase has members called assert: tell whether it is correct,
        self.assertEqual(formatted_name,"Tom Lee") : #. assertEqual method to determine whether the result is equal to "Tom Lee". The result is true or false. Run this method: no need to create an instance of this class. This class inherits from unittest.TestCase, and the method name starts with test, so it can be written directly
if __name__=='main__':  #If the current file is the main file and the running file is the current file, call unitest.mian to help us execute
    unittest.main()  #The operation results are as follows
                  

unittest.main(), as shown in the following figure
Test result: the program runs successfully

The content of the program has been changed so that the program fails to run. The test results are as follows:

The test results will tell:
AssertionError: 'Tom Lee'! = 'Tom Lee', assertion error, running time, running failure, number of failures.

Test class

Illustrate with examples

class Coder:
    def __init__(self,name): #The two attributes name and skill, name is passed to it, skill is added after
        self.name = name
        self.skills = [] #Skills can or can not be transferred from the initializer above. Object's skills may be multiple, put it in the list.
    def mastering_skill(self,skill):
        self.skills.append(skill)

    def show_skills(self):
        print('Mastering skills:')
        for skill in self.skills:
            print('-',skill) #Print current skills

# Instantiated class
c = Coder('Tom')
c.mastering_skill('Python')
c.mastering_skill('C#')
c.show_skills()                                 

To test this class, write a test case:
This test case should not be put together with the class to be tested, but should be written in a separate script.

For example, here, coder.py is the script of the class to be tested, and test UU coder.py is the test case.
Next write the test case, test UU coder.py:

import unittest
from coder import Coder #Import coder class from coder module

# Write a test case,
class CoderTestCase(unittest.TestCase): #Inherited from unittest.TestCase
    def test_skill_in(self):
        c = Coder('Tom') # Create an instance c and let it acquire some skills
        c.mastering_skill('Python')
        c.mastering_skill('ASP.NET MVC')
# Next, judge whether a skill is in the list,
        self.assertIn('Python',c.skills) # self refers to the class of test cases. Now assert whether a certain skill is in the list of mastered skills, and judge whether python is in c.skills. You can also judge other contents, so the assertion function called is different

if __name__=='__main__':
    unittest.main()
           

Operation result:

The left side tells which test is running,
Write the assert function assert to the class, and the pycharm operation interface changes to the test result interface:
All Test Passed
Or the test fails:

There is a problem with the test result. There is a problem in the test skill. The prompt is: AssertionError: ,

What are the assert functions tested / asserted
Test class, work to be instantiated
If you often test classes, you don't need to write them yourself. Most of them have been written for you. What are the common ones.
1. The test class needs to be instantiated. As we prepared an instantiation function: setup
To test a lot of information about programmers, go to new by yourself every time, so you can def setup(self) - initialize work and create programmer instances

import unittest
from coder import Coder 

class CoderTestCase(unittest.TestCase): 
# def setup(self) - initializes work and creates a programmer instance
    def setup(self):
        self.c = Coder('Tom') #self.c is equivalent to creating an instance of Coder. Next, prepare the skills
        self.c.skills = ['Python','.NET'] #In this way, if you test later, you don't need to write one line,
    def test_skill_in(self):
        self.assertIn('Pythons',self.c.skills) #To judge directly, is Python in self.c.skills?

if __name__=='__main__':
    unittest.main()

python official test module: unittest

unit testing

1. After our code or project is completed, we need to test whether its function is complete / correct before we deliver the deployment.
2. After defining a function, we need to perform a series of operations, such as returning a result, calculating a value, and printing a result. Before we integrate the current function or method into the current system, we need to test the current function function, such as whether the value passed by me is the result I want after calculation. Specific conditions are given to determine whether the results meet the expectations.
3. Why write test cases?
It is a way to run the results on the console to see if they meet the expectations.
Unit testing, according to the functions provided by his framework, is more convenient to test. Compared with the testing of the whole program, unit testing simplifies the testing task,
4. Unit test is mainly used in Python,

According to different levels, tests are divided into several categories:

Test level:

1. Unit test
The smallest unit test is unit test, which tests the most basic unit of code: function / method,
2. Integration test
After developing a functional module, there may be multiple modules that need to be integrated, which will involve integration testing. To integrate it into the system, system testing will be required.
3. System test
4. Acceptance test
Acceptance tests will be required prior to acceptance
5. Regression test
If problems are found in the actual deployment or application process, iterative testing or development may be required, which requires regression testing
6. After defining a function, we need to perform a series of operations, such as returning a result, calculating a value, and printing a result. Before we integrate the current function or method into the current system, we need to test the current function function, such as whether the value passed by me is the result I want after calculation. Specific conditions are given to determine whether the results meet the expectations.

Test code organization

Organizing code, using unit test framework

import unittest #

def add(a,b):
    return a + b

#Define a class of its own, and let it inherit from unittest.TestCase is called the base class of test case
class MyTset(unittest.TestCase): #Write your own test case method function in the class. That is, to test what function, you need to define this function into a function, and the Convention is that the qualified function always starts with "test". For example, to test the add method
    def test_add(self) # Because this function inherits from unittest.TestCase and is a class itself, it is an instance method. To test whether the result of the add method written is correct
        self.assertEqual(8,add(5,3)) # assertEqual, whether the assertions are equal. Now the logic is: use the derived class written by the base class provided by the unit test module to define a test function,
       
# Note: when testing next, do not use the following print(result), do not call manually, use unittest.main() method: main entry, which is a specific rule
if __name__ == '__main__':
    unittest.main()

Run this script at an interactive prompt:

Operation result ok
Change the code content to: self.assertEqual(8,add(5,4)), result:

The above example runs in pycharm:

Which test is running is shown on the left,
What is running is the mytest class under the MyTest script, and the test function is test add.
If everything is ok, what you see on the right is green, indicating that everything is normal.
If it's red, it means it can't pass the test.
After understanding this mechanism, you can write multiple test case functions in the test case class.
For example, define other contents:

import unittest 
"""unit testing
"""

def add(a,b):
    return a + b

def subtract(a,b):
    return a - b

class MyTset(unittest.TestCase): 
    def test_add(self): 
        self.assertEqual(8,add(5,4))

    def test_subtract(self):
        self.assertEqual(2,subtract(5,3))
       
if __name__ == '__main__':
    unittest.main()

Function:

Test add is wrong, and test subtract is normal.
The organization of the code. The functions defined by ourselves are not written into the class as methods, but are put into the current script as ordinary functions, which can be directly used for testing. In actual development, functions are put into classes as methods.

Common assertion methods in python

Judge whether the function test result is correct or not, and use the method of assertion
There are several conventions, which are the requirements of the test device: first of all, you have to write a class by yourself and inherit from unittest.TestCase. Your test method starts with test UU. The main function of the test case is main() under unittest to help us start.
Although unit testing is the most basic unit of our program, mainly testing functions and methods, it is not necessarily necessary to write a ready-made function to help us.

Example 1:

Create a new assert method.py file
This lesson is to demonstrate the assertion method of the test, so prepare several basic data structures in the front.

import unittest 

#First, the variables of a person are stated, and described in a dictionary;
person = {'name':'Mike','age':20}
numbers = [1,3,2,88,7,44]
s = 'Superior class codeclassroom.com'

# Create a test case class: write a test case into a class, called class TestAssert, which inherits from the TestCase case case under unittest. Then there is a self (current member) in the function. You can point out many methods starting with aeest as follows:
class TestAssert(unittest.TestCase): #The method of defining test? Assert? Method in the class
    def test_assert_method(self):
        self.assertEqual('Mlike',person.get('name'))#assertEqual method to determine whether two values are equal: the first string and the last expression (the expression is the result returned by the function we defined). Now it's time to get the name in the person dictionary table.
        self.assertTrue('Superior class' in s)
        self.assertIn('Superior class',s) #It is specially used to judge whether the former is in the latter
        self.assertAlmostEqual(3.3,1.1+2.2)
        self.assertIs(True+1,2)
        self.assertIsNone(person.get('Name',None)) #If there is a Name key in person, if it does not return None, it will pass.
        self.asserIsInstance(s,str) #Let's see if the type of S is str
        self.asserIsInstance(numbers[0],int)
        self.assertGreater(-7,numbers[0]) #Is it greater than
# Write program entry
if __name__ == '__main__': 
    unittest.main()

See the following figure for aeest starting method
1.assertEqual method to determine whether two values are equal

2.asserttrue
If the defined function is executed, the returned result may be true or false boolean type, then we will use to determine whether the result is equal to true or false. asserttrue
3.assertin
4. Assert almostequal is approximately equal to
self.assertEqual(3.3,1.1+2.2), because the results before and after are floating-point, because of the computer precision, the results are not equal, so the results can not pass. If the business logic allows this kind of error to exist, it can be judged by assert almost equal,
5. Assert is used to determine whether two objects are the same reference
6. Assert is None
7. Assertistinstance judgment type

There are many ways to achieve the same function, and you can choose a more familiar method.

Class and test device


In the actual development, there may be several packages and modules under my project, which contain their own codes. These codes can be directly organized into functions instead of being object-oriented, put under my modules, or written into object-oriented, class based or method based structures.
Now I want to write a class, called calculator. At this time, I don't pay attention to testing. I want to write it with need, I don't pay attention to the content of unit testing, I just write my own business logic,
Define a class

class Calculator:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def add(self):
        return self.x + self.y
    def subtract(self):
        return self.x - self.y

# Do not consider unit tests. To see the results, you have to print by yourself. Because this is a class, you have to create an instance by yourself
if __name__ == '__main__':
    c = Calculator(5,3)
    print(c.add())     

Now the business logic is organized in the form of class plus method. If you want to test, you will usually create a subdirectory under the directory he relies on: test, which contains some test cases.

For example, calculator.py, I write a test case corresponding to it: calculator_test.py: it is specially used to test my business logic
calculator_test.py content:

import unittest #Import test module
# Because the tested class is in the outer layer, it also needs to be imported
from calculator import Calculator #Imported for testing
#Next, write a test case class
class CalculatorTest(unittest.TestCase): #Methods of writing test cases in classes
    def test_add(self): #Since our method definition is defined in the instance, we need to first new an instance before clicking add
        c = Calculator(5,3)
        self.assertEqual(8,c.add()) #self refers to the calculator test case, which has nothing to do with the previous type. In this way, only one method can be tested. To test weight loss, you have to write another one
     def test_subtract(self):
         c = Calculator(8,4)
         self.assertEqual(4,c.subtract())

if __name__ == '__main__':
    unittest.main()                 

Question: just now I defined my business logic method into a class and organized it into instance functions. So I have to recreate an instance every time I define a test case function. It's too troublesome. Can I not define it every time and put it in a public place so that every test case function can find it.

In the prepared unittest.TestCase, a special function, * * setup (meaning of setting / preparing for installation) is prepared. The function: once you run the self-defined CalculatorTest test case, some work that needs to be prepared can be written into setup. It is possible that multiple test case methods need to use an instance, which can be written into setup.
The setup function is to do the initialization work. The initialization content is to prepare the following test cases.

import unittest 
from calculator import Calculator 

class CalculatorTest(unittest.TestCase):
    def setup(self): #
        self.c = Calculator(5,3) #At present, the instance of this test case is prepared with a method called c. how does c come from? It is constructed through the Calculator class. Advantage: in the future, each function below will not need to be reconstructed when it needs to use the class instance.
    def test_add(self): 
        #c = Calculator(5,3) no need to construct
        self.assertEqual(8,c.add()) 
        
     def test_subtract(self):
         #c = Calculator(8,4) no need to construct
         self.assertEqual(4,c.subtract())

    def tearDown(self): #After the test, the resources in it should be cleared
        del self.c

if __name__ == '__main__':
    unittest.main()   

The setup also includes: the preparation of some cause and effect context, including the linked database, which may be used for testing in the future,
After the test, the resources inside may need to be cleared. For example, if the database link is opened, the link is dedicated to the test. After the test, the link should be closed. There is a tearDown function: you can clean up.
In the actual development, it is assumed that the file is opened, then the handle of the file is released, the database link is opened, and the link is closed after the test.

Published 11 original articles, won praise 3, visited 1707
Private letter follow

Keywords: Python calculator Database Attribute

Added by dvt85 on Thu, 13 Feb 2020 05:25:50 +0200