python - 测试 Flask 应用程序时保留多个功能的更改

标签 python testing flask pytest

我正在关注 Flask 上关于创建 API 的演讲。我想为它写一些测试。在测试创建资源时,测试删除另一个功能中的资源是否有效?如何使资源的创建持久化以进行删除和编辑测试?

David Baumgold - Prototyping New APIs with Flask - PyCon 2016

演讲展示了如何为小狗的名字和图片 url 制作 API。

  • 您使用 POST 请求在索引页创建了一只小狗
  • 你从'/puppy_name'得到了一只小狗
  • 你从'/'得到了小狗的列表
  • 您使用来自“/puppy_name”的 PUT 编辑一只小狗(当然还有新数据)
  • 你从“/puppy_name”删除了一只小狗
import py.test
import unittest
from requests import get, post, delete, put

localhost = 'http://localhost:5000'

class TestApi(unittest.TestCase):
    def test_list_puppies(self):
        index = get(localhost)
        assert index.status_code == 200

    def test_get_puppy(self):
        puppy1 = get(localhost + '/rover')
        puppy2 = get(localhost + '/spot')
        assert puppy1.status_code == 200 and puppy2.status_code == 200

    def test_create_puppy(self):
        create = post(localhost, data={
            'name': 'lassie', 'image_url': 'lassie_url'})
        assert create.status_code == 201

    @py.test.mark.skip('cannot fix it')
    def test_edit_puppy(self):
        ret = put(localhost + '/lassie',
                  data={'name': 'xxx', 'image_url': 'yyy'})
        assert ret.status_code == 201

    def test_puppy_exits(self):
        lassie = get(localhost + '/lassie').status_code
        assert lassie == 200

    def test_delete_puppy(self):
        ret = delete(localhost + '/lassie')
        assert ret.status_code == 200
@app.route('/', methods=['POST'])
def create_puppy():
    puppy, errors = puppy_schema.load(request.form)
    if errors:
    response = jsonify(errors)
    response.status_code = 400
    return response

    puppy.slug = slugify(puppy.name)

    # create in database
    db.session.add(puppy)
    db.session.commit()

    # return an HTTP response
    response = jsonify( {'message': 'puppy created'} )
    response.status_code = 201
    location = url_for('get_puppy', slug=puppy.slug)
    response.headers['location'] = location

    return response

@app.route('/<slug>', methods=['DELETE'])
def delete_puppy(slug):
    puppy = Puppy.query.filter(Puppy.slug == slug).first_or_404()
    db.session.delete(puppy)
    db.session.commit()

    return jsonify( {'message': '{} deleted'.format(puppy.name)} )

“test_edit_puppy”和“test_puppy_exists”中的断言语句均失败。我得到 404 状态代码而不是 201 和 200。

最佳答案

你在测试错误的东西。您可以在运行测试时简单地通过提交它来持久保存对数据库的更改,但您真的不想这样做。

通过单元测试,您可以测试简单的单元。对于集成测试,这就是您在这里谈论的内容,您仍然希望每个测试都有一个特定的重点。在这种特殊情况下,您可能希望执行以下操作:

def test_delete_puppy(self):
    create = post(localhost, data={
        'name': 'lassie', 'image_url': 'lassie_url'})        
    lassie = get(localhost + '/lassie')

    # not sure if there's an "assume" method, but I would
    # use that here - the test is not a valid test
    # if you can't create a puppy and retrieve the puppy
    # then there's really no way to delete something that
    # does not exist
    assert create.status_code == 201
    assert lassie.status_code == 200

    ret = delete(localhost + '/lassie')
    assert ret.status_code == 200

    lassie = get(localhost + '/lassie')
    assert lassie.status_code == 404

此测试的重点是测试删除小狗是否正常。但是您希望将数据库中的小狗设置为测试的一部分或测试设置的一部分。它是 arrange, act, assertarrange 部分。在实际执行测试之前,您要按正确的顺序安排世界的状态。集成测试和单元测试之间的区别在于,对于单元测试,您将模拟出您正在调用的所有端点,而对于集成测试,您将在运行测试之前实际设置所需的所有数据部分。这就是您想在此处执行的操作。

关于python - 测试 Flask 应用程序时保留多个功能的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38437820/

相关文章:

python - 多处理问题

testing - 重置 FB Like 按钮

javascript - 如何测试 Node 数据分块功能

python - SQLAlchemy automap - 向自动映射模型添加方法

python - 尝试从 dockerized Python 脚本连接时出现 FTP 错误 "500 Illegal PORT command"

python - 如果在包根目录中,则无法导入 C++ 扩展

python - 这有效,但为什么?

python - 3 级列表理解

ruby-on-rails - Webrat 说它找不到一些文本,但文本实际上在那里

python - Python 中的 Flask 测试——在 repo 中构建一个 API,通过 import_module 对其进行单元测试