??????????????????TDD????????????????????????????????????????????????????飬?????????????????????????????????TDD??????????????????????????????????????????檔
???????????????????????????????????????????????????????????????????????????????????????????????????е??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????·????????????????????????????????
???????????????????????????????г????????????????д??????д????????????????£????е??????????????????????????????????????????Σ??????????????????汾??????????????????
?????????ApiTestEngine??????????TDD???????????????????????2???TDD??????????Щ?????????
??????API???????Mock Server??
???????????????????????????????п????API?????????????????????????????????????????????API?????????Mock Server??????????????TDD????????????????????????????????????????Ч?????????????
??????????????????е??????API?????????
????????????????????????????????????????????????????????????漰????????????????????????????????????????????????????????棬???????????????????????????書????????????????????????????????к????????ü????????????????????????????GET/POST/HEAD/PUT/DELETE??????????????????????е???????????GET/POST????
???????д?API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????y????????????????????????????У??????????????????????????????
???????????????Python??API????????????????????????Flask??????????
???????磬??????????????????????????????饗CRUD???????????????????洢?????????£?
????users_dict = {
????   'uid1': {
????       'name': 'name1'??
????       'password': 'pwd1'
????   }??
????   'uid2': {
????       'name': 'name2'??
????       'password': 'pwd2'
????   }
????}
???????????????Create??????£?Update??????????????????·??????
????import json
????from flask import Flask
????from flask import request?? make_response
????app = Flask(__name__)
????users_dict = {}
????@app.route('/api/users/<int:uid>'?? methods=['POST'])
????def create_user(uid):
????    user = request.get_json()
????    if uid not in users_dict:
????        result = {
????            'success': True??
????            'msg': "user created successfully."
????        }
????        status_code = 201
????        users_dict[uid] = user
????    else:
????        result = {
????            'success': False??
????            'msg': "user already existed."
????        }
????        status_code = 500
????    response = make_response(json.dumps(result)?? status_code)
????    response.headers["Content-Type"] = "application/json"
????    return response
????@app.route('/api/users/<int:uid>'?? methods=['PUT'])
????def update_user(uid):
????    user = users_dict.get(uid?? {})
????    if user:
????        user = request.get_json()
????        success = True
????        status_code = 200
????    else:
????        success = False
????        status_code = 404
????    result = {
????        'success': success??
????        'data': user
????    }
????    response = make_response(json.dumps(result)?? status_code)
????    response.headers["Content-Type"] = "application/json"
????    return response
??????????????????????????????????????????????????ο???????
??????????????????Flask??????????????????·???????????
????$ export FLASK_APP=test/api_server.py
????$ flask run
???? * Serving Flask app "test.api_server"
???? * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
?????????????????????????????????????????????????磬?????????????????????????????????Python????е???÷?????£?
????$ python
????Python 3.6.0 (default?? Mar 24 2017?? 16:58:25)
????>>> import requests
????>>> requests.post('http://127.0.0.1:5000/api/users/1000'?? json={'name': 'user1'?? 'password': '123456'})
????<Response [201]>
????>>> resp = requests.get('http://127.0.0.1:5000/api/users')
????>>> resp.content
????b'{"success": true?? "count": 1?? "items": [{"name": "user1"?? "password": "123456"}]}'
????>>>
?????????????????????????????????????
????????????????????? Mock Server
????API??????Mock Server???????????????????????е??????????????????????API???????????????????????????
???????????????????????ApiServerUnittest?????????????setUpClass?????????????API??????Mock Server???????tearDownClass????????????API??????????setUpClass???????????????????????????????Σ??????????????????????????е????API???????????????tearDownClass?????????????????????????????Σ???API?????????????????????????????
??# test/base.py
????import multiprocessing
????import time
????import unittest
????from . import api_server
????class ApiServerUnittest(unittest.TestCase):
????    """
????    Test case class that sets up an HTTP server which can be used within the tests
????    """
????    @classmethod
????    def setUpClass(cls):
????        cls.api_server_process = multiprocessing.Process(
????            target=api_server.app.run
????        )
????        cls.api_server_process.start()
????        time.sleep(0.1)
????    @classmethod
????    def tearDownClass(cls):
????        cls.api_server_process.terminate()
???????????????????????multiprocessing????????????????????????????API??????Mock Server???????С???????????????????locust??????????gevent.pywsgi.WSGIServer????????????????gevent?????????????monkey.patch_all()???о?????鷳??????????????gevent????????????????????????????????multiprocessing????????????????????????????threading????????????????????????????terminate????????????????????multiprocessing????????
?????????????????????????Server????????????????????????????????????????????0.1?????????????????е??????????????????API????????????????????
????ApiServerUnittest??????????????????Mock Server???????????????????????ApiServerUnittest???????????д??????????????????????
???????磬????????????????????????????“?????????????????????????”???????
# test/test_apiserver.py
????import requests
????from .base import ApiServerUnittest
????class TestApiServer(ApiServerUnittest):
????    def setUp(self):
????        super(TestApiServer?? self).setUp()
????        self.host = "http://127.0.0.1:5000"
????        self.api_client = requests.Session()
????        self.clear_users()
????    def tearDown(self):
????        super(TestApiServer?? self).tearDown()
????    def test_create_user_not_existed(self):
????        self.clear_users()
????        url = "%s/api/users/%d" % (self.host?? 1000)
????        data = {
????            "name": "user1"??
????            "password": "123456"
????        }
????        resp = self.api_client.post(url?? json=data)
????        self.assertEqual(201?? resp.status_code)
????        self.assertEqual(True?? resp.json()["success"])
???????????????????????饗Travis CI??
?????????????????е???????????????????????????????????飬????????????????GitHub??????в???????????????????????????????????е??