求教 Django test 问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
laoyur
V2EX    Django

求教 Django test 问题

  •  
  •   laoyur 2016-09-22 14:10:36 +08:00 2654 次点击
    这是一个创建于 3306 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以前没怎么写过 Test ,如有原则性错误请勿喷……

    我没有直接用 Django 的 TestCase ,而是用的 pytest-django ,但原理都差不多的

    我想达到如下的目的:

    import pytest @pytest.mark.django_db class Test_API: @classmethod def setup_class(cls): cls.client = APIClient() @classmethod def teardown_class(cls): pass def test_register(self): resp = self.client.put('/account/', { 'username': 'user1', 'password': 'pass1' }) assert resp.status_code == 200 def test_login(self): resp = self.client.post('/login/', { 'username': 'user1', 'password': 'pass1' }) assert resp.status_code == 200 def test_logout(self): r = self.client.get('/logout/') assert r.status_code == 200 

    我的目的是:先跑注册,再跑登录,最后登出,简单来说,我想编写有前后依赖关系的 test case 然而上面的代码运行结果如下:

    tests/test_api.py::Test_API::test_register PASSED tests/test_api.py::Test_API::test_login FAILED tests/test_api.py::Test_API::test_logout FAILED 

    问题的原因我知道,文档中也有说明,跟 Django 类似,每一个 test 跑完后,会自动 rollback 。这个原因导致了我上述目的无法达成。

    然而我很想知道,有没有办法禁用每一个 test 跑完后的自动 rollback?最好能让我在setup中手动开启 transaction ,在teardown中手动 rollback

    我找遍了 Django 、 pytest 、 pytest-django 的文档,不知道怎么搞。

    还是说我的思路根本就是错误的,不要写这种有依赖性的 test case

    4 条回复    2016-09-22 16:33:41 +08:00
    sylecn
        1
    sylecn  
       2016-09-22 15:33:33 +08:00   1
    流程性的东西,放到同一个 test case 里面做 setup 和 assert 。比如,如果我注册了一个用户,那么它应该可以正常登录。如果我发布了一条信息,那么应该能查询到这条信息。如果我删除了一条信息,那么应该无法查询到该信息。

    不同的测试之间可以共享测试数据(比如用户名,测试消息什么的)和 setup 代码(比如创建一组用户和数据用于测试),但是不要让不同的测试场景和测试用例互相依赖。互相依赖的测试,一旦有错误,无法准确定位问题。牵一发而动全身。对开发和测试都不好。
    laoyur
        2
    laoyur  
    OP
       2016-09-22 16:07:13 +08:00
    @sylecn 感谢回复

    如果在同一个 def test_register(self) 里面按顺序执行 register login logout ,是没有问题的,但我就是觉得 test 的 log 输出可读性不强(特指出现错误 case 的时候,不能一眼看过去就知道流程中哪个点出了问题)
    所以我才准备写一个 class-based testcase ,然后试图用里面的各 test_ 方法来表达各个被测试点

    暂时我先把注册 /登录封装成通用方法,然后在各 test_* 方法中按需调用吧,不知道有没有更优雅的方法
    sylecn
        3
    sylecn  
       2016-09-22 16:16:17 +08:00
    >> 觉得 test 的 log 输出可读性不强(特指出现错误 case 的时候,不能一眼看过去就知道流程中哪个点出了问题)

    @laoyur IDE 都是直接跳转到出错的那个 assert ,并且显示对应的 expect value 和 real value 。不知道你说的一眼看过去不容易看出哪个点是什么意思。实际做 TDD 的时候,通常都直接看错误的 assert 的代码行,不会去着重看测试名称的。
    laoyur
        4
    laoyur  
    OP
       2016-09-22 16:33:41 +08:00
    @sylecn 谢谢!

    现在把主帖中的代码换了一种写法,稍微看着顺眼一点了:

    import pytest


    @pytest.mark.django_db
    class Test_API:
    @classmethod
    def setup_class(cls):
    cls.client = APIClient()

    @classmethod
    def teardown_class(cls):
    pass

    def _test_register(self):
    resp = self.client.put('/account/', {
    'username': 'user1',
    'password': 'pass1'
    })
    assert resp.status_code == 200

    def _test_login(self):
    resp = self.client.post('/login/', {
    'username': 'user1',
    'password': 'pass1'
    })
    assert resp.status_code == 200

    def _test_logout(self):
    r = self.client.et('/logout/')
    assert r.status_code == 200

    def test(self):
    self._test_register()
    self._test_login()
    self._test_logout()
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2208 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 00:58 PVG 08:58 LAX 17:58 JFK 20:58
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86