首页 文章

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

提问于
浏览
0

我正在关于创建API的关于Flask的讨论 . 我想为它写一些测试 . 在测试创建资源时是否测试在另一个函数中删除资源?如何使资源的创建持久化以进行删除和编辑测试?

David Baumgold - Prototyping New APIs with Flask - PyCon 2016

该演讲展示了如何为小狗的名字和图片网址制作API .

  • 您在索引页面上创建了一个带有POST请求的小狗

  • 你从'/puppy_name'得到一只GET的小狗

  • 你从'/'获得了GET的小狗名单

  • 你用'/puppy_name'用PUT编辑一只小狗(当然还有新数据)

  • 从'/puppy_name'删除带有DELETE的小狗

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 .

1 回答

  • 3

    你正在测试错误的东西 . 您可以将更改保留到数据库,只需提交它,当您运行测试时,但您确实不想这样做 .

    通过单元测试,你在这里谈论,你仍然希望每个测试都有一个特定的焦点 . 在这种特殊情况下,您可能希望执行以下操作:

    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 部分 . 你're arranging the state of the world in its proper order before you actually perform the test. The difference between integration testing and unit testing is that with unit testing you' d嘲笑你在运行测试部分之前实际设置所需的所有数据的所有 endpoints . 这是你想要做的 .

相关问题