在本文中,我们将考虑使用Python软件包,Flask,使用MongoDB为我们的数据库创建API,创建Postman测试并使用Docker运行所有内容。
您可以在我的example-api repo中找到所有我会通过的代码。
设置容器
首先,我们将使用Docker-Compose设置容器。在新的项目文件夹中,创建一个具有以下内容的docker-compose.yml
文件:
version: '3.9'
services:
db:
image: mongo:5.0
ports:
- 27017:27017
networks:
- backend
env_file: .env
api:
build: ./
ports:
- 5000:5000
volumes:
- ./src:/src
networks:
- frontend
- backend
env_file: .env
postman:
image: postman/newman:alpine
command:
run ${POSTMAN_COLLECTION} -k
-r cli,json
--reporter-json-export="reports/api_test_report.json"
volumes:
- ./tests:/etc/newman
depends_on:
- "api"
- "db"
networks:
- backend
networks:
frontend:
backend:
我们有3个容器:
-
db
-用于我们的数据库,运行mongodb image -
api
-用于我们的烧瓶API,由Dockerfile
构建
-
postman
-用于测试我们的API,执行Postman Collection测试
烧瓶API
对于烧瓶API,创建一个Dockerfile
,并具有以下内容:
FROM python:3.8-slim-buster
WORKDIR /app
COPY src/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
使用requirements.txt
文件在项目文件夹中创建一个新的src
文件夹:
mkdir src
touch requirements.txt
对于requirements.txt
的内容,添加以下内容:
flask
flask-pymongo
建造我们的容器时,将安装这些软件包。
接下来,我们需要创建应用程序,在src
文件夹中创建一个app.py
文件:
import os
import json
from flask import Flask, request
from flask_pymongo import PyMongo
from bson import json_util, ObjectId
MONGODB_URI = os.environ.get("MONGODB_ENDPOINT")
app = Flask(__name__)
app.config["MONGO_URI"] = MONGODB_URI
mongo = PyMongo(app)
def parse_json(data):
return json.loads(json_util.dumps(data))
@app.route('/')
def hello_world():
return 'Hello, World!'
@app.route('/items', methods=['GET'])
def get_all_items():
items = list(mongo.db.items.find())
return parse_json(items), 200
@app.route('/items', methods=['POST'])
def create_item():
item = request.get_json()
inserted_item = mongo.db.items.insert_one(item)
return parse_json(inserted_item.inserted_id), 201
@app.route('/items/<item_id>', methods=['GET'])
def get_item(item_id):
item = mongo.db.items.find_one_or_404({'_id': ObjectId(item_id)})
return parse_json(item), 200
@app.route('/items/<item_id>', methods=['PUT'])
def update_item(item_id):
item = request.get_json()
item_id_obj = ObjectId(item_id)
result = mongo.db.items.update_one({'_id': item_id_obj}, {'$set': item})
if result.matched_count == 0:
return parse_json({'error': 'Item not found'}), 404
updated_item = mongo.db.items.find_one({'_id': item_id_obj})
return parse_json({'message': 'Item updated successfully', 'item': updated_item}), 200
@app.route('/items/<item_id>', methods=['DELETE'])
def delete_item(item_id):
item_id_obj = ObjectId(item_id)
result = mongo.db.items.delete_one({'_id': item_id_obj})
if result.deleted_count == 0:
return parse_json({'error': 'Item not found'}), 404
return parse_json({'message': 'Item deleted successfully'}), 200
if __name__ == "__main__":
app.run(debug=True)
这是我们的整个应用。在脚本的顶部,我们正在导入所需的软件包,初始化烧瓶应用程序和mongodb实例。
我们有一个parse_json
功能,用于格式化MongoDB的响应,hello_world
函数和用于创建,阅读,更新和删除记录的CRUD操作。
您可以在脚本中看到,我们使用的是环境变量,os.environ.get("MONGODB_ENDPOINT")
。要设置此问题,请在项目root目录中创建一个.env
文件,并使用以下内容:
MONGODB_ENDPOINT=mongodb://db:27017/example
POSTMAN_COLLECTION=Example_API.postman_collection.json
提出命令
最后,在项目root目录中创建一个Makefile
,并使用以下内容:
DOCKER_COMPOSE = docker-compose up -d
POSTMAN_COLLECTION ?=
.PHONY: rebuild
rebuild:
docker-compose up -d --build
.PHONY: start
start: _start_api _start_db
.PHONY: stop
stop:
docker-compose down
.PHONY: tests
tests:
@echo "Running tests"
docker-compose up postman
_start_api:
$(DOCKER_COMPOSE) api
_start_db:
$(DOCKER_COMPOSE) db
此Makefile允许我们轻松启动并停止Docker容器。
我们的start
命令仅启动api
和db
容器。仅当我们执行tests
方法时,postman
容器才能运行,该方法立即运行测试并终止容器。
运行API
到目前为止,您的项目目录应该看起来像这样:
.
├── Dockerfile
├── Makefile
├── docker-compose.yml
├── .env
└── src
├── app.py
└── requirements.txt
我们现在可以运行API!
要构建并启动API,运行:
make start
去http://localhost:5000。您应该看到一个“你好,世界!”消息:
ðAPI启动并运行!
API具有以下端点:
端点 | 方法 | 描述 |
---|---|---|
/ |
GET |
你好世界 |
/items |
GET |
获取所有项目 |
/items/{id} |
GET |
获取项目 |
/items |
POST |
创建项目 |
/items/{id} |
PUT |
更新项目 |
/items/{id} |
DELETE |
删除项目 |
如果要在API中添加测试,请继续阅读!
测试API
随着API的启动和运行,我们可以编写邮递员测试。
打开Postman并创建一个新系列。
单击集合名称,然后转到Variables
选项卡。
创建一个名为base_url
的新变量,具有初始值和当前值http://localhost:5000
。单击“保存图标”。
单击Add a request
并创建一个名为“ Hello World”的请求。这将是一个请求。将请求URL设置为{{base_url}}
,这将使用我们的集合变量中的值。单击Save
和Send
。
Postman将执行请求,您将在下面看到API的响应:
打开Tests
选项卡。在右边,有一个SNIPPETS
工具栏。在列表中,单击Status code: Code is 200
。这将添加这样的测试:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
单击Save
和Send
。该测试将在“ Test Results
”选项卡中运行并显示在输出面板中:
现在,我们已经为Hello World
端点设置了测试。现在我们需要为其他端点创建测试。
重复此过程,为每个端点创建新请求并测试:
获取所有项目
请求名称:获取所有项目
请求方法:获取
请求URL: {{base_url}}/items
测试:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
创建项目
请求名称:创建项目
请求方法:发布
请求URL: {{base_url}}/items
测试:
pm.test("Status code is 201", function () {
pm.response.to.have.status(201);
});
pm.test("Returned item id", function () {
jsonData = pm.response.json()
pm.collectionVariables.set("item_id", jsonData.$oid);
});
对于此测试,项目创建后的成功响应状态代码为201
。我们还进行了第二次测试,以获取我们创建的项目的返回的item_id
并将其设置为集合变量。然后,我们可以在未来测试中使用该值。
身体:
由于这是POST
请求,我们将通过内容发送以创建项目。在Body
选项卡中,单击raw
并粘贴以下内容:
{
"title": "Hello, World!"
}
执行请求时,此内容将发送到我们的API。
获取项目
请求名称:获取项目
请求方法:获取
请求URL: {{base_url}}/items/{{item_id}}
测试:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Returned result matches test item", function () {
jsonData = pm.response.json()
item_id = pm.collectionVariables.get("item_id");
pm.expect(jsonData._id.$oid).to.eql(item_id);
pm.expect(jsonData.title).to.eql("Hello, World!");
});
此请求使用收集值中保存的item_id
。在测试中,我们正在检查响应成功(200
),并验证返回的item_id
并与我们在Create Item
测试中创建的内容匹配。
更新项目
请求名称:更新项目
请求方法: put
请求URL: {{base_url}}/items/{{item_id}}
测试:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Result contains updated item", function () {
jsonData = pm.response.json()
item_id = pm.collectionVariables.get("item_id");
pm.expect(jsonData.item._id.$oid).to.eql(item_id);
pm.expect(jsonData.item.title).to.eql("Hello, there!");
});
再次,此请求使用收集值中保存的item_id
。这次,我们正在检查返回的item_id
与我们修改的项目匹配,而title
与我们的请求Body
中的更新值匹配。
身体:
{
"title": "Hello, there!"
}
删除项目
请求名称:删除项目
请求方法:删除
请求URL: {{base_url}}/items/{{item_id}}
测试:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
执行所有测试
随着所有请求和测试添加到我们的集合中,我们可以一起运行它们。
单击集合名称旁边的三个点,然后单击Run collection
。单击Run Example API
执行所有测试。
Postman将通过您的API上的测试进行摘要:
â如果一切都正确设置,所有测试都应成功!
自动化测试
可以通过单击“集合名称”和“ Export
”旁边的三个点来导出包含请求和测试的邮政集合。将收藏集导出到您的项目文件夹中,并将其引入一个名为tests
的新文件夹。命名集合Example API.postman_collection.json
。
在我们项目中的收藏中,我们可以运行make tests
。这将运行postman
容器并执行测试。您可能会注意到所有测试都失败了。这是因为base_url
变量设置为http://localhost:5000
,并且在从postman
容器中运行时,烧瓶API是无法实现的。
要解决此问题,请将--env-var "base_url=${API_BASE_URL}"
添加到docker-compose.yml
中定义的邮政容器中:
postman:
image: postman/newman:alpine
command:
run ${POSTMAN_COLLECTION} -k
--env-var "base_url=${API_BASE_URL}"
-r cli,json
--reporter-json-export="reports/api_test_report.json"
volumes:
- ./tests:/etc/newman
depends_on:
- "api"
- "db"
networks:
- backend
并将API_BASE_URL=http://api:5000
添加到.env
文件:
MONGODB_ENDPOINT=mongodb://db:27017/example
POSTMAN_COLLECTION=Example_API.postman_collection.json
API_BASE_URL=http://api:5000
api
是指docker-compose.yml
中定义的api
docker容器。通过使用此功能,postman
容器将能够到达烧瓶API。现在重新运行make tests
,他们都应该成功。
github动作
在项目目录中,创建一个.github
文件夹,其中的workflows
文件夹和一个test.yml
文件:
mkdir .github
mkdir .github/workflows
touch .github/workflows/test.yml
在.github/workflows/test.yml
文件中,添加以下内容:
name: Test API
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test-api:
environment:
name: tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: make tests
提交并将您的更改推向github。当推动更改或创建main
的拉普尔时,github操作将运行make tests
:
ð您现在有一个带有自动测试的示例API!
如果您陷入了任何步骤,或者只是想要完整的解决方案,请参考或克隆我的example-api repo。