current position:Home>Untested Python code is not far from crashing
Untested Python code is not far from crashing
2022-01-31 07:51:16 【Nuggets translation program】
- Original address :Untested Python Code is Already Broken
- Original author :Matthew Hull
- The translation comes from : Nuggets translation plan
- Permanent link to this article :github.com/xitu/gold-m…
- translator :jaredliw
- Checked by :ItzMiracleOwO、KimYangOfCat
My first mentor was incredibly . He showed me the code 、 logging 、 Best practices and benefits of documentation . But there's one thing he couldn't instill in me , That's the test . His way of testing code is complicated , Including writing the test program first , And then coding implementation ! His way is opposite to my coding style , It makes me feel :" If I write the test before I write the function , Then I might as well not write a test .”…… It makes me feel much better .
But the problem is : Your code needs to be tested . Because all the code , Even good code , Both with bug There is only a thin line between them . For starters :bug Is an unexpected function or error in the code . You may know your code and its limitations very well , But new teammates ? perhaps , In a year , You want to add a feature to a project you've largely forgotten , What should I do ? The test is like a bumper on a bowling alley , So that you can be confident that the submitted code will get full marks every time .
This article will reuse my Python In the learning series The first 3 part Code for , And use me in here To introduce the Makefile
. If you are Python Novice , Why don't you take a look first The first 1 part and The first 2 part ? Besides , If you don't have your own Python The work environment , Please be there. here Check out the tutorials you need .
Topics discussed :
- unit testing
- Inherit
- Mocking and patch
- Makefile
- When to test ?
Because this requires some code , I've created a Github Project To help us start this topic . The easiest way to get it is through Github Desktop Clone it , Or download it as ZIP file . The folder contains order_up.py
、 One Makefile
And a Pipfile
, One more Solutions
Folder , But let's ignore it for the time being .
Create a file called tests
Of Python package . So how to create ? It's a little complicated —— First, create a folder , Create a file named __init__.py
Empty file . Yes , That's it . And then in the new tests
In the folder , Create another one called test_order_up.py
The file of . Now we can start . Be careful :unittest( and pytest) According to “test” The beginning of the file determines the test code , So avoid this when naming non test files !
What is the test ?
In short , The test answered “ Whether the execution results of the program meet our expectations ?” This problem . To answer this question , We can run a function by using preselected input and check whether the output meets our expectations . You can run a function and verify the output , Make sure it doesn't throw errors , Or make sure it exactly Throw an error , To ensure that the code has been fully tested . A good set of tests should include normal use cases 、 Edge use cases and creative use cases . You don't just have to make sure your code runs as it is , And make sure your The test will capture any stupid behavior you or others will do in the future .
Unittest
Unittest yes Python Built in test framework , So we'll start here . Put this code into your test file :
import unittest
import order_up
class TestOrderUp(unittest.TestCase):
def test_get_order_one_item(self):
order = ["fries"]
result = order_up.get_order(order)
self.assertEqual(order, result)
Copy code
First , We import unittest
, It is a tool for testing code Python Built in bag , And then we import order_up.py
file ( Notice that we have omitted .py
Extension ).
notes : If you're using PyCharm And in
order_up
See the red underline below , This means that the package cannot be found . You can go back to Github Open the project under the root directory of the project or right-click the project folder and select “Mark Directory as” -> “Sources Root” To solve this problem .
Next , Let's create a name TestOrderUp
Class , Its name matches our file name , This makes it easier to find failed tests . Oh , But there's something in parentheses ,unittest.TestCase
, This means that our class inherits TestCase
class .
Inherit
Inheritance means that a class receives functions and variables from its parent class . In our case , We from TestCase
It inherits rich functions to facilitate our testing work . What functions and variables are inherited ? We'll discuss this later .
Create a test
Under our class is a class named test_output_order_one_item
Function of , It should roughly explain what we do in the test . We will use it to test get_order()
Function and check whether the output meets our expectations . Let's run it , See what happens ! You can execute... In the terminal python -m unittest
, Or click PyCharm The green arrow next to the function in . You can also choose to perform make unit-test
, Let the code run in a virtual environment ( We will mention later Makefile
). Look at the results :
Assertion (assert)
We from unittest.TestCase
Functions inherited in include assertions , It ensures that the result of the function is within our expectations . stay Pycharm in , Input self.assert
, The code completion function will display all the different options . There are a lot of them , But I mainly use self.assertEqual
, It checks whether the two objects are the same , as well as self.assertTrue
/self.assertFalse
, The function is self-evident .
Now? ,order_up
The main function of is to get orders , Delete items that are not on the menu , And allow duplicate items . therefore , Let's add tests to make sure we keep these functions in our code .
# Make sure these functions are indented in the class .
def test_get_order_duplicate_in_list(self):
order = ["fries", "fries", "fries", "burger"]
result = order_up.get_order(order)
self.assertEqual(order, result)
def test_get_order_not_on_menu(self):
order = ["banana", "cereal", "cookie"]
expected_result = ["cookie"]
result = order_up.get_order(order)
self.assertEqual(expected_result, result)
Copy code
Now we are checking whether our function can handle duplicate items and items not on the menu . Run these tests and make sure they pass ! sidenote : It's best to write a test with a line between the executed code and the verified code . such , You and your teammates can easily tell which is which .
Patch
I have to admit : I did a little cheating . If you will The first 3 part The code in is the same as the current order_up.py
Compare , You will notice that I added a function to accommodate a new variable :test_order
. With this new variable , We can bypass the introduction of input()
, In this way, we won't let the program ask the user for input every time we run the test . But now we have mastered the basic knowledge of testing , We can start trying to use mock.Mock Can imitate and create functions / object , So that our tests can focus on logic . under these circumstances , We will “ Mend ” input()
function , Or rewrite it temporarily , To simply return the output we want . have a look :
@patch("builtins.input", return_value="yes")
def test_is_order_complete_yes(self, input_patch):
self.assertEqual(builtins.input, input_patch)
result = order_up.is_order_complete()
self.assertFalse(result)
Copy code
First , Add... At the beginning of the test file from unittest.mock import patch
. In limine , We are mending builtins.input()
Function and tell it to return “yes”. then , We execute assertions to check whether the parameters obtained from the patch are consistent with input
It's exactly the same ! be aware builtins.input
Are there no parentheses ? We can reference the signature of the function to verify , Instead of executing functions . after , Let's go back to the normal test protocol : Operation function , To get the results , And assert the result . under these circumstances , Because of our input()
The return value is “yes”, We expect is_order_complete()
return False
. Add it to your test class , Click Run , Get red OK Or green check mark , Let's move on !
Side Effect
Now we've learned patch, We can solve get_output()
The input problem in ! Um. , almost . First , We need to understand side_effect
, When we need to provide different return values for the same function , It is our Savior . stay get_output()
in , adopt input()
, We were asked “ What do you want ?” and “ Have you finished? ?”. therefore , We need to get input()
Not just one but multiple outputs are returned to accommodate each situation . have a look :
@patch("builtins.input", side_effect=["banana", "cookie", "yes", "fries", "no"])
def test_get_order_valid(self, input_patch):
self.assertEqual(builtins.input, input_patch)
expected_result = ["cookie", "fries"]
result = order_up.get_order()
self.assertEqual(expected_result, result)
Copy code
So , We don't know return_value
, It's for side_effect
Assign a list .
remarks : You can also assign values in the test function
side_effect
orreturn_value
.
side_effect
Will get each item in the list , And in every call patch Function is provided separately . Add the code and click the test button / command ! The last thing : stay “banana” and “cookie” None of them is / no , Because if MENU
The item does not exist in ,get_order()
Don't ask “ Would you like to order more ?”. If you want to play with this list yourself , Please remember this thing .
Makefile
Having finished the basics of testing , Let's take a look Makefile
. I won't copy / Paste the code here , Because you can see it in the project . The main method is unit-test
and run
.unit-test
need venv
To execute , According to our Pipfile
Configure and start a virtual environment . Pay attention to unit-test
At the end of , We did python3 -m pipenv run python3 -m unittest;
, This is where testing magic takes place , Even if you forget how to run tests , You can also find it there !
When to write tests ?
So when to write a test ? It doesn't matter . The point is that the test written can cover most of the code and the potential use cases it may encounter . If you can't test your code correctly or need to 8 A different test to cover a function , Then you probably need to refactor your code . This doesn't make you a bad programmer , It's just a programming process / Part of the experience .
Test-driven development (TDD)
Let me talk about test driven development (TDD) The question of .TDD Is a development practice , Write the failed test program first, and then write the function to pass it . Story time : I joined a startup , The startup will Robert C. Martin(《 Clean code 》 And the authors of other books ) Of TDD And the concept of negative patterns , Or bad coding practices to avoid , As a faith . There is a , We held a meeting on TDD And its benefits of meetings to encourage the team to think more “ It works ” The way to code . Unfortunately , Spend most of your time arguing TDD On the definition and correct usage of . The organizer of the meeting , A senior engineer , Think we “ Coding too fast ”, Not by writing " smart " Tests or functions that exceed the functions tested to correctly implement TDD Principles .
I left the meeting with an idea : Let your philosophical debate from my work disappear .
The point of this article is : Find a suitable way to include testing in the project . I didn't give a specific way to implement them or when , As long as they can prevent your code from entering the drain after the next submission . bye !
If there are errors in the translation or other areas that need to be improved , Welcome to Nuggets translation plan Revise the translation and PR, You can also get bonus points . At the beginning of the article Permanent link to this article That's what this article is about GitHub Upper MarkDown link .
Nuggets translation plan It is a community that translates high-quality Internet technology articles , The source of the article is Nuggets Share articles in English on . Content coverage Android、iOS、 front end 、 Back end 、 Blockchain 、 product 、 Design 、 Artificial intelligence Other fields , If you want to see more excellent translations, please keep your eyes on Nuggets translation plan 、 Official micro-blog 、 Know about columns .
copyright notice
author[Nuggets translation program],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201310751094389.html
The sidebar is recommended
- Django ORM details - fields, attributes, operations
- Python web crawler - crawling cloud music review (3)
- Stroke list in python (bottom)
- What cat is the most popular? Python crawls the whole network of cat pictures. Which one is your favorite
- [algorithm learning] LCP 06 Take coins (Java / C / C + + / Python / go / trust)
- Python shows the progress of downloading files from requests
- Solve the problem that Django celery beat prompts that the database is incorrectly configured and does not support multiple databases
- Bamboolib: this will be one of the most useful Python libraries you've ever seen
- Python quantitative data warehouse construction 3: data drop library code encapsulation
- The source code and implementation of Django CSRF Middleware
guess what you like
-
Python hashlib module
-
The cover of Python 3 web crawler development (Second Edition) has been determined!
-
The introduction method of executing Python source code or Python source code file (novice, please enter the old bird and turn left)
-
[Python basics] explain Python basic functions in detail, including teaching and learning
-
Python web crawler - crawling cloud music review (4)
-
The first step of scientific research: create Python virtual environment on Linux server
-
Writing nmap scanning tool in Python -- multithreaded version
-
leetcode 2057. Smallest Index With Equal Value(python)
-
Bamboolib: this will be one of the most useful Python libraries you've ever seen
-
Python crawler actual combat, requests module, python realizes capturing a video barrage
Random recommended
- [algorithm learning] 1108 IP address invalidation (Java / C / C + + / Python / go / trust)
- Test platform series (71) Python timed task scheme
- Java AES / ECB / pkcs5padding encryption conversion Python 3
- Loguru: the ultimate Python log solution
- Blurring and anonymizing faces using OpenCV and python
- How fast Python sync and async execute
- Python interface automation test framework (basic) -- common data types list & set ()
- Python crawler actual combat, requests module, python realizes capturing video barrage comments of station B
- Python: several implementation methods of multi process
- Sword finger offer II 054 Sum of all values greater than or equal to nodes | 538 | 1038 (Java / C / C + + / Python / go / trust)
- How IOS developers learn python programming 3-operator 2
- How IOS developers learn python programming 2-operator 1
- [Python applet] 8 lines of code to realize file de duplication
- Python uses the pynvml tool to obtain the working status of GPU
- Data mining: Python actual combat multi factor analysis
- Manually compile opencv on MacOS and Linux and add it to Python / C + + / Java as a dependency
- Use Python VTK to batch read 2D slices and display 3D models
- Complete image cutting using Python version VTK
- Python interface automation test framework (basic) -- common data types Dict
- Django (make an epidemic data report)
- Python specific text extraction in actual combat challenges the first step of efficient office
- Daily python, Part 8 - if statement
- Django model class 1
- The same Python code draws many different cherry trees. Which one do you like?
- Python code reading (Chapter 54): Fibonacci sequence
- Django model class 2
- Python crawler Basics
- Mapping 3D model surface distances using Python VTK
- How to implement encrypted message signature and verification in Python -- HMAC
- leetcode 1945. Sum of Digits of String After Convert(python)
- leetcode 2062. Count Vowel Substrings of a String(python)
- Analysis of Matplotlib module of Python visualization
- Django permission management
- Python integrated programming -- visual hot search list and new epidemic situation map
- [Python data collection] scripy realizes picture download
- Python interface automation test framework (basic part) -- loop statement of process control for & while
- Daily python, Chapter 9, while loop
- Van * Python | save the crawled data with docx and PDF
- Five life saving Python tips
- Django frequency control