为Python REST API函数编写单元测试

时间:2020-07-16 16:00:25

标签: python python-3.x

我目前正在学习Python REST API(辅助项目)。我一直在阅读RealPython,Python Requests文档等中的许多教程。我发现了这篇关于如何在Python(Correct way to try/except using Python requests module?)中正确编写try / except的文章。令我困惑的是,如何为这样的函数创建单元测试,因为它不返回任何内容。有帮助吗?

def google_do_something(blahblah):
    url='http://www.google.com/' + blahblah
    try:
        r = requests.get(url,timeout=3)
        r.raise_for_status()
    except requests.exceptions.HTTPError as errh:
        print (errh)
    except requests.exceptions.ConnectionError as errc:
        print (errc)
    except requests.exceptions.Timeout as errt:
        print (errt)
    except requests.exceptions.RequestException as err:
        print (err)

我可以想到这一点,但是我不知道该怎么断定。

def test_google_do_something():
    g = google_do_something('blahblah')
    # assert??

3 个答案:

答案 0 :(得分:2)

我不确定您的方法是不是一个好主意(只是在出现错误的情况下打印某些内容),但是您可以模拟print函数以查看它是否真的被调用(以及带有什么参数):

https://docs.python.org/3/library/unittest.mock.html?highlight=mock#module-unittest.mock

编辑:

据我所知,使用模拟程序有些棘手。您将不得不在当前模块中模拟打印功能。也许是这样的(未测试... ):

from unittest.mock import patch
from unittest import TestCase

class TestGoogleDoSomething(TestCase)
    
    @patch("nameOfYourModule.print")
    def test_google_do_something(self, print_mock): # the decorator will pass the mock object into the function
        g = google_do_something('blahblah')
        print_mock.assert_called_with("your error message here ...")

答案 1 :(得分:1)

Python提供了几种单元测试框架。 try / except块可以很好地处理错误,但是如果要对它进行单元测试,则仍然需要在调用周围进行单独的单元测试。

您确实有可以测试的东西,您可以将其返回并在单元测试中进行测试。

使用unittest的示例单元测试:

import unittest
import requests

class RestCalls():

    def google_do_something(blahblah):
        url= blahblah
        try:
            r = requests.get(url,timeout=1)
            r.raise_for_status()
            return r.status_code
        except requests.exceptions.Timeout as errt:
            print (errt)
            raise
        except requests.exceptions.HTTPError as errh:
            print (errh)
            raise
        except requests.exceptions.ConnectionError as errc:
            print (errc)
            raise
        except requests.exceptions.RequestException as err:
            print (err)
            raise


class TestRESTMethods(unittest.TestCase):

    def test_valid_url(self):
        self.assertEqual(200,RestCalls.google_do_something('http://www.google.com/search'))

    def test_exception(self):
        self.assertRaises(requests.exceptions.Timeout,RestCalls.google_do_something,'http://localhost:28989')

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

执行应显示(对此帖子进行了一些编辑,更新后的输出包含在帖子底部):

> python .\Tests.py
 .
----------------------------------------------------------------------
Ran 1 test in 0.192s

OK

如果您断言了与请求不同的响应代码,则它将失败(该请求仅返回http响应代码):

python .\Tests.py
F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\Tests.py", line 25, in test_upper
    self.assertEqual(404,RestCalls.google_do_something('search'))
AssertionError: 404 != 200

----------------------------------------------------------------------
Ran 1 test in 0.245s

FAILED (failures=1)

希望。

编辑:包括的异常测试。您可以通过在except块中加入 raise 来进行测试,运行后将显示以下内容:

> python .\Tests.py
HTTPConnectionPool(host='localhost', port=28989): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x03688598>, 'Connection to localhost timed out. (connect timeout=1)'))
..
----------------------------------------------------------------------
Ran 2 tests in 2.216s

OK

参考:

答案 2 :(得分:0)

似乎您使用的是print而不是所有异常处理程序。我认为这不是一个好习惯。从我的角度来看,如果不确定现在如何处理这些异常,我希望再次提出这些异常。

话虽如此,当发生任何错误时,都会抛出异常;如果没有例外,则表示此功能运行良好。因此,您可以在此基础上设计单元测试用例。