Chapter 11 test code
11.1 test function
name_function.py(File name, not code) def get_formatted_name(first, last): """Generate a neatly formatted full name.""" full_name = first + ' ' + last return full_name.title()
Program names Py allows users to enter first and last names and display neat full names:
from name_function import get_formatted_name print("Enter 'q' at any time to quit.") while True: first = input("\nPlease give me a first name: ") if first == 'q': break last = input("Please give me a last name: ") if last == 'q': break formatted_name = get_formatted_name(first, last) print("\tNeatly formatted name: " + formatted_name + '.')
This program starts from name_ function. Import get from PY_ formatted_ name(). The user can enter a series of first and last names and see the fully formatted first name:
Enter 'q' at any time to quit. Please give me a first name: janis Please give me a last name: joplin Neatly formatted name: Janis Joplin. Please give me a first name: bob Please give me a last name: dylan Neatly formatted name: Bob Dylan. Please give me a first name: q
11.1.1 unit test and test cases
The module unittest in Python standard library provides code testing tools. Unit tests are used to verify that there is no problem with one aspect of the function; A test case is a set of unit tests that work together to verify that the behavior of the function meets the requirements in various situations. Good test cases take into account the various inputs that the function may receive, including tests for all these situations. Full coverage test cases include a complete set of unit tests, covering various possible function use modes. For large projects, it may be difficult to achieve full coverage. Usually, at first, you only need to write tests for the important behavior of the code, and then consider full coverage when the project is widely used.
11.1.2 acceptable tests
To write test cases for functions, you can first import the module unittest and the functions to be tested, and then create an inherited unittest Testcase class, and write a series of methods to test different aspects of function behavior.
import unittest from name_function import get_formatted_name class NamesTestCase(unittest.TestCase): """test name_function.py""" def test_first_last_name(self): """Be able to handle images correctly Janis Joplin Such a name?""" formatted_name = get_formatted_name('janis', 'joplin') self.assertEqual(formatted_name, 'Janis Joplin') unittest.main()
This class must inherit unittest Testcase class, so that Python knows how to run the test you write.
We run test_name_function.py, all are marked with test_ The first methods will run automatically.
We used one of the most useful features of the unittest class: an assertion method. The assertion method is used to verify whether the results obtained are consistent with the expected results. Here, we know_ formatted_ name() should return a name whose first and last names are capitalized with a space between them, so we expect formatted_ The value of name is Janis Joplin. To check whether this is true, we call the method of unittest, assertEqual(), and pass it formatted_ name and 'Janis Joplin'. Code line self Assert equal (formatted_name, 'Janis Joplin') means: "compare the value of formatted_name with the string 'Janis Joplin'. If they are equal, everything will be fine. If they are not equal, tell me!"
The code line unittest Main () lets Python run the tests in this file. Run test_name_function.py, the output is as follows:
. ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
The period in line 1 indicates that one test has passed. The next line indicates that Python ran a test that took less than 0.001 seconds. The final OK indicates that all unit tests in the test case have passed.
11.1.3 failed tests
The following is the function get_ formatted_ The new version of name(), which requires the middle name to be specified through an argument:
name_ function.py(File name, not code) def get_formatted_name(first, middle, last): """Generate neat names""" full_name = first + ' ' + middle + ' ' + last return full_name.title()
This version should be able to handle names with middle names correctly, but when we tested it, we found that it can no longer be used
Correctly handle names with only first and last names. Run the program test this time_ name_ function. Py, the output is as follows:
E ====================================================================== ERROR: test_first_last_name (__main__.NamesTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_name_function.py", line 8, in test_first_last_name formatted_name = get_formatted_name('janis', 'joplin') TypeError: get_formatted_name() missing 1 required positional argument: 'last' ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1)
The output of line 1 has only one letter E, which indicates that a unit test in the test case caused an error. Next, we see test in NamesTestCase_ first_ last_ Name() caused an error. When a test case contains many unit tests, it is important to know which test failed. We see a standard traceback that indicates the function call get_formatted_name('janis', 'joplin') has a problem because it lacks an essential location argument. We also saw a unit test run. Finally, you see a message indicating that the entire test case failed because an error occurred while running the test case.
11.1.4 what to do if the test fails
What if the test fails? If the conditions you check are correct, passing the test means that the behavior of the function is correct, and failing the test means that the new code you write is wrong. Therefore, when the test fails, do not modify the test, but repair the code that causes the test to fail: check the modification just made to the function to find out the modification that causes the function behavior not to meet the expectations.
11.1.5 add new test
11.2 testing
11.2.1 various assertion methods
Python in unittest Many assertion methods are provided in the testcase class. As mentioned earlier, the assertion method checks whether the conditions you think should be met are indeed met. If this condition is indeed met, your assumption of program behavior is confirmed, and you can be sure that there is no error in it. If the condition you think should be met is not actually met, python will throw an exception.
The following table describes six common assertion methods. Use these methods to verify that the returned value is equal to or not equal to the expected value, that the returned value is True or False, and that the returned value is in or not in the list. You can only inherit unittest Use these methods in testcase's class,
11.2.2 a class to be tested
survey.py(File name, not code) class AnonymousSurvey(): """Collect answers to anonymous questionnaires""" def __init__(self, question): """Store a question and prepare for storing an answer""" self.question = question self.responses = [] def show_question(self): """Display questionnaire""" print(question) def store_response(self, new_response): """Storage of individual survey responses""" self.responses.append(new_response) def show_results(self): """Display all collected answers""" print("Survey results:") for response in responses: print('- ' + response)
To prove that the AnonymousSurvey class works correctly, let's write a program that uses it:
from survey import AnonymousSurvey #Define a question and create an anonymous survey object that represents the survey question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) #Display questions and store answers my_survey.show_question() print("Enter 'q' at any time to quit.\n") while True: response = input("Language: ") if response == 'q': break my_survey.store_response(response) # Display survey results print("\nThank you to everyone who participated in the survey!") my_survey.show_results()
When the user enters all the answers (after entering q to exit), call show_. Results() to print the survey results:
What language did you first learn to speak? Enter 'q' at any time to quit. Language: English Language: Spanish Language: English Language: Mandarin Language: q Thank you to everyone who participated in the survey! Survey results: - English - Spanish - English - Mandarin
11.2.3 testing anonymous survey
import unittest from survey import AnonymousSurvey class TestAnonmyousSurvey(unittest.TestCase): """in the light of AnonymousSurvey Class testing""" def test_store_single_response(self): """Test individual answers will be stored properly""" question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) my_survey.store_response('English') self.assertIn('English', my_survey.responses) unittest.main()
When we run test_survey.py, the test passed:
. ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
That's good, but surveys that collect only one answer are of little use. Let's verify that when the user provides three answers, they will also be properly stored. To do this, we add another method in TestAnonymousSurvey:
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """in the light of AnonymousSurvey Class testing""" def test_store_single_response(self): """Test individual answers will be stored properly""" --snip-- def test_store_three_responses(self): """The three answers to the test will be stored properly""" question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) responses = ['English', 'Spanish', 'Mandarin'] for response in responses: my_survey.store_response(response) for response in responses: self.assertIn(response, my_survey.responses) unittest.main()
We run test again_ survey. When you pass the test for both answers (py) and (py):
.. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
11.2.4 method setUp()
unittest. The TestCase class contains the method setUp(), which allows us to create these objects only once and use them in each test method. If you include the method setUp() in the TestCase class, Python will run it first, and then run each to test_ The way to start. In this way, the object created in method setUp() can be used in every test method you write
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """in the light of AnonymousSurvey Class testing""" def setUp(self): """ Create a survey object and a set of answers for the test method used """ question = "What language did you first learn to speak?" self.my_survey = AnonymousSurvey(question) self.responses = ['English', 'Spanish', 'Mandarin'] def test_store_single_response(self): """Test individual answers will be stored properly""" self.my_survey.store_response(self.responses[0]) self.assertIn(self.responses[0], self.my_survey.responses) def test_store_three_responses(self): """The three answers to the test will be stored properly""" for response in self.responses: self.my_survey.store_response(response) for response in self.responses: self.assertIn(response, self.my_survey.responses) unittest.main()
The method setUp() does two things: create a survey object; Create a list of answers. The variable names that store these two things contain the prefix self (that is, stored in attributes), so they can be used anywhere in this class. This makes both test methods easier because they don't have to create respondents and answers.
Note: when running test cases, Python prints a character every time a unit test is completed: a period is printed when the test passes; Print an E when the test causes an error; Print an F when the test causes the assertion to fail. That's why when you run a test case, you see different numbers of periods and characters in the first line of output. If the test case contains many unit tests and needs to run for a long time, you can know how many tests have passed by observing these results.
11.3 summary
In this chapter, you learned how to use the tools in the module unittest to write tests for functions and classes; How to write inheritance unittest Testcase classes and how to write test methods to verify that the behavior of functions and classes meets expectations; How to use the method setUp() to efficiently create instances and set their properties based on the class so that they can be used in all test methods of the class.