程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

How to improve the robustness of Python code through testing

編輯:Python

0x00 Preface
This article is more about Python Back end programmers . Let me share my understanding of writing tests .

In this issue, let's talk about testing .

The contents of this article are as follows :

▼ How to improve through testing Python The robustness of the code : section
0x00 Preface : section
▼ 0x01 Classification of tests : section
What tests does the back end mainly focus on : section
▼ 0x02 Why write tests : section
Let novices understand the code faster : section
Make the code release more confident : section
Make the program easier to refactor : section
Accelerate team development : section
▼ 0x03 Why not write tests : section
Problems that testing cannot solve : section
Why is inappropriate testing a burden : section
Not all places are easy to test : section
▼ 0x04 Write Python Some considerations for testing : section
Environmental isolation of the project : section
The basic environment for testing : section
Single measurement / Dynamometer / end-to-end : section
How to handle external services : section
other Pytest Tips : section
0xEE Reference resources : section

0x01 Classification of tests
There are many kinds of tests , According to the method of test design, it can be divided into :1. Black box 2. White box

According to the test purpose :

  1. A functional test
    unit testing
    A functional test
    Integration testing
    Scenario test
    A/B test
  2. Non functional testing
    Pressure test
    Safety test
    Accessibility testing
    other
    regression testing
    Ease of use test
    Many more , Too lazy to tidy up .....

Code coverage as the name suggests , That is, the proportion of test cases covering running code .

What tests does the back end mainly focus on

  • unit testing
  • A functional test
  • End to end testing
  • Performance testing

0x02 Why write tests
Let's talk about the advantages of testing .

Why write tests to cover code .

  1. Proper testing can give you more confidence when you release your code .
  2. Proper testing can help novices understand the code faster .
  3. Proper testing can make the program easier to refactor .
  4. Proper testing can speed up team development .

It's not like not writing , Nor is it crazy to write . You may have some doubts here ? Writing tests also speeds up ?Are you kidding?

Explain one by one .

Take a simplified example ,『 Users to place the order 』 To 『 Customer receiving 』.

  1. user 『 Query products 』
  2. user 『 Use coupons 』 Place an order
  3. user 『 Pay online 』. Of course , The user can also make no payment , Invalidate the order . Or cancel the order directly .
  4. merchants 『 Confirm delivery 』.
  5. The logistics company updates the waybill 『 In shipment 』.
  6. user 『 Confirm receipt 』. Of course , The user can also initiate a refund .

Let novices understand the code faster
The data in the test case , It is often the best test data set that can run through a piece of code .

If , A programmer wrote 『 Place an order - Pay online - Confirm receipt 』 Integration testing . As the person who just took over the code . In the shortest possible time , Understand the whole process by reading the test code .

Yes fixture, Novices can know in a very short time setup Basic data that can make the project run

Of course , If you write too many tests , It can also make reading difficult .

Make the code release more confident
Write tests , To verify that the code is working correctly .

A process , It usually contains several sub processes , The subprocess is right , The whole process is right .

If you don't write tests, you can fully cover some key processes , Will lead to
Modify or add a sub process , It is necessary to run a new process for human flesh test .
If the human flesh test is too cumbersome , The average programmer will skip this step and cause online problems .

Make the program easier to refactor
When you know that writing test code has so many advantages , Your first reaction is , I know that , however , Writing tests can also speed up development ?

Of course , You need to know , A valuable product that needs to be maintained , It is often necessary to constantly modify the process .

In limine ,PM Tell you that you only need to place an order to buy something , later , To add the full discount , Later, various types of coupons will be added , Then you have to connect with third-party services , Then you have to deal with all kinds of users who don't follow the process you set ….

Write tests , By constantly adding some tests , Realize the test automation of the whole process . Form a set of test code to test the project . The process is so long , You count on human flesh to test ?

    1. When I modify or add sub processes , On the test code that has been built , A small amount of code can be used to directly ensure that the input and output of modified or newly added sub processes are tested in place .
  1. When there are many people working together , If A Originally, a set of sub processes were maintained , and B To change the wave A Written sub process . With proper testing , Basically, the problem is solved , Will not run the test .

Of course , Premise is

  1. A Write the test carefully , Instead of writing something that just makes A The code runs past the tests .
  2. But if you write too many tests , It will also cause the team to be distracted . This will be known when we talk about the disadvantages of testing .

Accelerate team development
Although I say , What I write is to speed up the development of the team , But actually , It also applies to individuals .
Unless , You write rendered pages …. What you see is what you get . No testing required

0x03 Why not write tests
According to the software world famous 『 There is no silver bullet 』 theory , Having said the superiority of the test , Let's also talk about the limitations of testing , There are three main points :

  1. Testing doesn't solve any problems ?
  2. Improper testing , It is often a burden .
  3. Not all places are easy to test .

Problems that testing cannot solve
Testing can ensure the running quality of the code , But you can't guarantee the quality of your code , There is no guarantee that the product design logic problems .

in other words

  1. Bad code , Testing the code only ensures that the code is working properly . Does not improve code quality . At most, it can provide better running guarantee for the refactoring of bad code .
  2. Problems in product design logic , The test code can only guarantee the implementation of the design logic .

When you find it hard to write test code , You should consider refactoring your program .

Why is inappropriate testing a burden
What people have to get used to is :

  1. thing , There is no end to learning . The unknown always exists . New things are always emerging , Old things are also evolving .
  2. Time is limited , Energy co., LTD.

Put it on the test , test , It can't be measured .

Wrote a IF ELSE , You need to test two groups , Wrote one more IF ELSE, You will test four groups . If it is a complicated process , Basically, it's hard to finish a comprehensive test .

My idea is :

  1. Select key places to test
  2. Reduce unnecessary data acquisition by users

Not all places are easy to test

Not all places are easy to test .

  1. Especially rely on the business of other service providers . such as , Alipay / Advance payment of wechat . Login of wechat applet .
  2. Cross end business .

If this kind of business is done in depth , need Mock Lose a lot of logic .

0x04 Write Python Some considerations for testing
Environmental isolation of the project
From the perspective of the overall project , The environment in which the code runs should distinguish between Local/Test/Stage/Prod Four environments .

  • The local environment : The environment on the developer's computer
  • Test environment : On the developer's computer / Continuous integration environment , I used to like to use GitlabCI, later The team is on jenkins, It's OK to use .
  • Pre release environment : Pre release environment , For the back end , Usually, the front end can call API Environment .
  • Production environment : Production environment .

The reason for this distinction , It's because different environments have different priorities .

  • Local Environmental Science For developers , The code in this environment changes frequently .Web application / Worker / Beat / Deamon In a local environment , Generally, there are many errors , Usually I will ban the log .
  • Test Environmental Science Used to perform make lint && make test, Used for inspection lint Related code and run tests .
  • Stage Environmental Science
  • Prod Environmental Science and Stage The environment is closer . But it's not exactly the same . For example, some development materials of production environment organizations or businesses .

The basic environment for testing
Generally, there is one Docker-Compose file , To quickly initialize the test environment .

such as WebApp / Celery Worker / Celery Beats / Redis / RabbitMQ / MySQL Sure make start Start these services directly .

Single measurement / Dynamometer / end-to-end
I said before , The backend needs to pay attention to the following tests

  • unit testing
  • A functional test
  • End to end testing
  • Performance testing

Performance testing can generally monitor where the system has bottlenecks in advance . See the scene , Generally, observation and monitoring will make it easier to predict the bottleneck of the system , This is more about tuning , Let's put it later .

The framework assumes that we use Flask , Suppose there is such a BBS( I know you want to roast about why you use your blog /BBS For example , Too lazy to explain too much background knowledge about business scenarios , flee …)

  1. organization Organization Released a Thread

  2. user User In this Thread the Reply 『 Unregistered users can see 』

  3. Administrators Admin Found out User It seems that some information should not be published . Delete Reply.『 Unregistered users cannot see / The owner is visible 』

  4. Last User Make a complaint ,Admin I found that the things released were quite OK Of , Give through .『 Unregistered users can see 』

    tests # Test file directory ├── init.py ├── conftest.py # Here are collections that may be referenced by subdirectories ├── e2e # 『 End to end testing 』 │ ├── init.py │ ├── test_viewer.py │ ├── test_user.py │ ├── test_admin.py │ └── test_organization.py ├── functional # 『 A functional test 』 │ ├── init.py │ ├── test_do_simple_reply.py │ ├── test_do_complex_reply.py │ └── test_helper.py ├── unit # 『 unit testing 』 | ├── init.py | ├── test_auth.py | └── test_calc_some_thing.py ├── test_auth_helper.py # Store the basic code used to switch identities ├── test_const.py └── test_factory_helper.py # It can be used to initialize data in batches

This process is not complicated , But enough to write a test .

  1. stay test_factory_helper Complete the basic initialization of data .
  2. Simple test browsing in end-to-end testing . Contains unregistered users viewer The interview of ,user/admin/org The band of is valid / Invalid / Expired login credentials to access
  3. stay unit Test some logic that is not closely related to the business . such as , computing time
  4. stay functional Conduct independent tests . Sometimes I will pull up several functions for testing . Relatively independent tests , Just a new one User Of Thread, Delete Reply, Pull up to test 1/2/3/4 One test is over .

The former is simpler , The latter is relatively closer to integration testing . Each have advantages and disadvantages . I usually do a few more pull-up tests on key processes .

But the pull-up test has one more problem to solve , namely , User login authentication . You call a Service When , As an anonymous user / User's identity / Admin / Org Called .

That is, when calling different Service When it comes to solving problems , You may need to switch identities quickly . After identity switching, speed switching back . therefore ,test auth helper Come out .helper There's a switch as function , Every time you need to switch identities , hold g The login snapshot in the variable g.user g.admin g.org push To LocalStack In the stack (from werkzeug.local import LocalStack), Call complete Service Again Pop come out .

Pull it up to test the effect is like this .

def test_complex_process(org, user, admin):
with switch_as_org(org) as org: # 1. organization Organization Released a Thread
thread = publish_thread_by_org()
with switch_as_user(user) as user: # 2. user User In this Thread the Reply
reply = reply_thread(thread)
assert reply
with switch_as_anonymous() as anonymous_user:
_thread = see_thread(thread)
assert reply in _thread.replies # 『 Unregistered users can see 』
with switch_as_admin() as admin: # 3. Administrators Admin Found out User It seems that some information should not be published . Delete Reply.
delete_reply(reply)
assert reply.deleled
with switch_as_anonymous() as anonymous_user:『 Unregistered users cannot see 』
_thread = see_thread(thread)
assert reply not in _thread.replies
# ad locum , My identity is still user
_thread = see_thread(thread)
assert reply in _thread.replies # 『Ower Users can see 』
# 4. Last User Make a complaint ,Admin I found that the things released were quite OK Of , Give through .『 Unregistered users can see 』

As a developer , You just need to make the test run smoothly and the basic development is completed . In the process , You can also better comb your code .

How to handle external services
When pulling it up for testing , If we have one more process , Users can pay appreciation through wechat reply, This has to rely on external services .

And when you pull it up for testing , There will be a very embarrassing problem , Because the interfaces above me are of large granularity , I appreciate the very small process in this process , You must go through wechat http request .

The solution is simple .mock Drop the function requesting wechat . Call the payment callback function manually , that will do .

Of course , about http request , You can also use responses This artifact is used to quickly mock Artifact requests Of response

The general usage is as follows

def mock_success_pay():
def request_callback(request):
headers = {}
dispatch_callback(data=data)
return 200, headers, resp_body
responses.add_callback(
responses.POST,
PAY_URL,
callback=request_callback,
content_type="application/json",
)
@responses.activate
def test_pay(user):
mock_success_pay()
switch_as_user(user) as u:
order = pay_order(u)
assert order.status == "PAID"

other Pytest Tips
sometimes ipdb Than pdb It is not only a little better to use . How to be in pytest For internal use ?

pytest -v --pdb --pdbcls=IPython.terminal.debugger:Pdb

The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved