`
hanyh
  • 浏览: 235241 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

doctest写测试非常爽:)

阅读更多
最近用django作点小项目,直接使用doctest,用起来真爽.
注意几点:
1,每个测试用例加注释,最好和对应的Ticket联系起来
2,当前Client工具足够好用
可以通过status_code,context,content来测试自己的view是否正确
3,可以直接查看models的数据,非常方便
4,比unittest的无用代码量少多了

示例代码如下:
有个tribe的app
中间建了一个tests的目录
tribe/tests$ more __init__.py
# coding=UTF-8
from django.contrib.auth.models import User
from tribe.forms import *
from tribe.models import *
from django.test import Client
import os
from django.contrib.auth.models import Permission

TEST_ROOT = os.path.dirname(__file__)

import doctst
__test__ = {
    'Doctest': doctst
}


测试代码:
# coding=UTF-8
"""
>>> User.objects.all()
[]
>>> admin =  User.objects.create_user('admin', 'admin@foo.com', 'eeeee')
>>> admin.save()



#Ticket #2 用户登录 account.custom_login
>>> browser = Client()

#invalid login
>>> response = browser.post('/accounts/login/', {'username': 'orphan_user', 'password': 'xxx', 'remember':0})
>>> response.status_code
200

#valid login with username
>>> response = browser.post('/accounts/login/', {'username': 'admin', 'password': 'eeeee', 'remember':0})
>>> response.status_code
302

#valid login with email
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'admin@foo.com', 'password': 'eeeee', 'remember':0})
>>> response.status_code
302



#Ticket #5 小组类别列表 ,包括创建 create_category,list_category
>>> Category.objects.all()
[]
>>> response = browser.post('/accounts/login/', {'username': 'admin@foo.com', 'password': 'eeeee', 'remember':0})

#create root category
>>> response = browser.post('/group/category/create/', {'name': 'music'})
>>> Category.objects.all()
[<Category: music>]
>>> response = browser.post('/group/category/create/', {'name': 'book'})

#create sub category
>>> response = browser.post('/group/category/1/create/', {'name': 'classic'})
>>> response = browser.post('/group/category/1/create/', {'name': 'artist'})

#can't create
>>> response = browser.post('/group/category/3/create/', {'name': 'third level categroy'})
>>> response.status_code
403
>>> Category.objects.getList()
[{'category': <Category: music>, 'count': 2, 'child_set': [<Category: classic>, <Category: artist>]}, {'category': <Category: book>, 'count': 0, 'child_set': []}]

#小组首页 list_category
>>> Category.objects.getList(0,1)
[{'category': <Category: music>, 'count': 2, 'child_set': [<Category: classic>, <Category: artist>]}]
>>> category = Category.objects.all()[0]
>>> category.name
u'music'
>>> response = browser.get('/group/')
>>> len(response.context['objects'])
2

#查看特定小组 view_category
>>> response = browser.get('/group/category/1/')
>>> response.context['objects']
[<Category: classic>, <Category: artist>]
>>> response = browser.get('/group/category/3/')
>>> response.context['objects']
[]



#Ticket #6 创建小组  create_tribe
>>> response = browser.post('/accounts/login/', {'username': 'admin@foo.com', 'password': 'eeeee', 'remember':0})
>>> img_path = os.path.join(TEST_ROOT,'default.jpg')
>>> f = open(img_path)
>>> response = browser.post('/group/category/3/create_tribe/', {'name': 'artist in china','desc':'group 1','icon':f})
>>> f.close()
>>> response.status_code
302
>>> response = browser.get('/group/category/3/')
>>> response.context['objects']
[<Tribe: artist in china>]

#重构加入小组功能
>>> Tribe.objects.all()[0].get_managers()
[<User: admin>]

#不能在top category中创建小组
>>> response = browser.post('/group/category/1/create_tribe/', {'name': 'artist in china','desc':'group 1'})
>>> response.status_code
403


#Ticket #7 用户加入小组 join_tribe
>>> tribe_user = User.objects.create_user('tribe_user','ee@eess.net','eeeee')
>>> tribe_user.save()
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'tribe_user', 'password': 'eeeee', 'remember':0})
>>> response.status_code
302
>>> response = browser.post('/group/1/join/')
>>> response.content
'{"msg": "msg", "result": "true"}'
>>> tribe = Tribe.objects.all()[0]

#存在最初的创建者
>>> tribe.members.count()
2

#unsubscribe_tribe
>>> response = browser.post('/group/1/quit/')
>>> tribe = Tribe.objects.all()[0]
>>> tribe.members.count()
1

>>> response = browser.post('/group/1/join/')

#Ticket #8new_topic test
>>> Topic.objects.all().count()
0
>>> response = browser.post('/group/1/new_topic/',{'title': 'test topic', 'content':'新内容'})
>>> response.status_code
302
>>> Topic.objects.all().count()
1

#invalid new topic form test
>>> response = browser.post('/group/1/new_topic/',{'title': '测试'})
>>> response.status_code
200
>>> Topic.objects.all().count()
1


#create a tmp user to test invalid new_topic
>>> t_user = User.objects.create_user('t_user','ee@e3.net','eeeee')
>>> t_user.save()
>>> response = browser.post('/accounts/login/', {'username': 't_user', 'password': 'eeeee', 'remember':0})
>>> response = browser.post('/group/1/new_topic/',{'title': '测试', 'content':'新内容'})
>>> response.status_code
403

#Test invalid reply
>>> response = browser.post('/group/topic/1/reply/',{'content':'新内容'})
>>> response.status_code
403


#Test valid replay
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'tribe_user', 'password': 'eeeee', 'remember':0})
>>> response.status_code
302
>>> response = browser.post('/group/topic/1/reply/',{'content':'replay 1'})
>>> Reply.objects.all().count()
1
>>> response = browser.post('/group/topic/1/reply/',{'content':'replay 2'})
>>> response = browser.post('/group/topic/1/reply/',{'content':'replay 3'})
>>> response = browser.post('/group/topic/1/reply/',{'content':'replay 4'})


#小组话题列表Ticket #9 topic_list
>>> response = browser.post('/group/1/new_topic/',{'title': 'topic1', 'content':'新内容'})
>>> response = browser.post('/group/1/new_topic/',{'title': 'topic2', 'content':'新内容'})
>>> response = browser.post('/group/1/new_topic/',{'title': 'topic3', 'content':'新内容'})
>>> response = browser.get('/group/1/')
>>> response.status_code
200
>>> response.context['topics']
[<Topic: test topic>, <Topic: topic1>, <Topic: topic2>, <Topic: topic3>]

#查看话题 view_topic
>>> response = browser.get('/group/topic/1/')
>>> response.context['topic']
<Topic: test topic>
>>> response.context['topic'].reply_set.all()
[<Reply: replay 1>, <Reply: replay 2>, <Reply: replay 3>, <Reply: replay 4>]



#Ticket #12查看话题 list_member
>>> response = browser.get('/group/1/member/')
>>> response.context['members']
[<User: admin>, <User: tribe_user>]

#Ticket #13自己加入 my_tribe
#current user:tribe_user
>>> response = browser.get('/group/mine/')
>>> response.context['tribes']
[<Tribe: artist in china>]

>>> Tribe.objects.all()
[<Tribe: artist in china>]

#创建小组加入
>>> response = browser.post('/group/category/3/create_tribe/', {'name': 'artist in china 2','desc':'group 2'})
>>> response = browser.post('/group/category/3/create_tribe/', {'name': 'artist in china 3','desc':'group 3'})
>>> response = browser.post('/group/category/3/create_tribe/', {'name': 'artist in china 4','desc':'group 4'})


>>> response = browser.post('/group/1/join/')
>>> response = browser.post('/group/2/join/')
>>> response = browser.post('/group/3/join/')

>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'tribe_user', 'password': 'eeeee', 'remember':0})
>>> response = browser.get('/group/mine/')
>>> response.context['tribes']
[<Tribe: artist in china>, <Tribe: artist in china 2>, <Tribe: artist in china 3>, <Tribe: artist in china 4>]
>>> response = browser.get('/group/1/quit/')
>>> response = browser.get('/group/mine/')
>>> response.context['tribes']
[<Tribe: artist in china 2>, <Tribe: artist in china 3>, <Tribe: artist in china 4>]

>>> response = browser.post('/group/1/join/')

>>> response = browser.get('/group/1/latest_member/')
>>> response.context['memberships']
[<Membership: tribe_user is a member of 'artist in china'>, <Membership: admin is a member of 'artist in china'>]

Ticket #14 我的发言
>>> response = browser.get('/group/1/my_topic/')
>>> response.context['topics']
[<Topic: test topic>, <Topic: topic1>, <Topic: topic2>, <Topic: topic3>]

Ticket #15
>>> Tribe.objects.all()
[<Tribe: artist in china>, <Tribe: artist in china 2>, <Tribe: artist in china 3>, <Tribe: artist in china 4>]

>>> User.objects.all()
[<User: admin>, <User: tribe_user>, <User: t_user>]

>>> tribe = Tribe.objects.get(pk=1)
>>> tribe.name
u'artist in china'
>>> tribe.get_managers()
[<User: admin>]

>>> User.objects.get(pk=2).username
u'tribe_user'
>>> User.objects.get(pk=3).username
u't_user'

#添加管理员
>>> response = browser.post('/group/1/grant/2/')
>>> response.status_code
403

#添加管理员
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'admin', 'password': 'eeeee', 'remember':0})
>>> response = browser.post('/group/1/grant/2/')
>>> response.content
'{"msg": "", "result": true}'

>>> tribe.get_managers()
[<User: tribe_user>, <User: admin>]

#删除管理员
>>> response = browser.post('/group/1/revoke/2/')
>>> response.content
'{"msg": "", "result": true}'

#小组搜索
>>> response = browser.get('/group/search/',{'search_text': 'china 3'})
>>> response.context['tribes']
[<Tribe: artist in china 3>]

#删除组员
>>> tribe.get_members()
[<User: tribe_user>, <User: admin>]
>>> tribe.get_managers()
[<User: admin>]

>>> response = browser.get('/group/1/del_tribe_user/3/')
>>> response.content
'{"msg": "not a tribe user.", "result": false}'

>>> response = browser.get('/group/1/del_tribe_user/1/')
>>> response.content
'{"msg": "can\\\'t delete tribe creator", "result": false}'

>>> response = browser.get('/group/1/del_tribe_user/2/')
>>> response.content
'{"msg": "delete tribe user successfully.", "result": true}'

>>> Topic.objects.all()
[<Topic: test topic>, <Topic: topic1>, <Topic: topic2>, <Topic: topic3>]

#都是trib user
>>> Topic.objects.all()[0].creator
<User: tribe_user>

#no permission
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 't_user', 'password': 'eeeee', 'remember':0})
>>> response = browser.get('/group/topic/1/del_topic/')
>>> response.status_code
403

#creator 
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'tribe_user', 'password': 'eeeee', 'remember':0})
>>> response = browser.get('/group/topic/1/del_topic/')
>>> response.status_code
302


#管理员可以删除
>>> Topic.objects.all()[2].tribe.get_managers()
[<User: admin>]
>>> admin = User.objects.get(username='admin')
>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 'admin', 'password': 'eeeee', 'remember':0})
>>> response = browser.get('/group/topic/2/del_topic/')
>>> response.status_code
302



#有权限删除
>>> t_user = User.objects.get(username='t_user')
>>> t_user.user_permissions.all()
[]
>>> p = Permission.objects.get(codename="del_topic")
>>> t_user.user_permissions.add(p)
>>> t_user.save()
>>> a = User.objects.get(username='t_user')
>>> a.user_permissions.all()
[<Permission: tribe | topic | Can delete tribe topics>]
>>> a.has_perm('tribe.del_topic')
True

>>> browser.logout()
>>> response = browser.post('/accounts/login/', {'username': 't_user', 'password': 'eeeee', 'remember':0})
>>> response = browser.get('/group/topic/3/del_topic/')
>>> response.status_code
302


"""
分享到:
评论

相关推荐

    cpp-doctest最轻的特性丰富的C单个header的测试框架

    **cpp-doctest:轻量级且功能强大的C++单头测试框架** `cpp-doctest`是一种高效的、功能丰富的C++测试框架,它以其简洁的API和仅需一个头文件的特性,深受C++开发者的喜爱。这个框架允许开发者在代码中轻松地编写...

    doctest-lib:https:github.comonqtamdoctest的CMake包装器,使生活更轻松

    很棒的C ++单元测试库包装。 它使使用该库作为带有CMake的子模块更加容易。 它有一个CMakeLists.txt,它本身没有任何内容。 应该由add_subdirectory添加。 然后,它定义了两个静态库目标: doctest这是一个没有...

    JSTester:两个小型应用程序,可以对javascript进行类似于doctest的测试

    小型Web应用程序,可以生成脚本以进行类似doctest的javascript测试 用法: 转到网络应用程序 粘贴doctest代码 点击开始 可选:单击“ MINIFY”(将所有内容放在一行上,更加干净)。 将代码粘贴到js脚本中 跑去看...

    前端开源库-doctest

    5. **与其他测试框架的集成**:尽管`doctest`是一个独立的测试工具,但也可以与Mocha、Jest等其他测试框架集成,以实现更全面的测试覆盖。 **doctest的优势** 1. **简洁性**:`doctest`鼓励编写清晰的文档,同时...

    自动化测试的利器:探索Python中的代码测试工具

    - **doctest**:这个工具允许开发者直接在文档字符串中编写测试用例,这些测试用例可以被自动执行,非常适合用于验证代码示例的正确性。 - **Behave**:这是一个 BDD(行为驱动开发)框架,用于编写和执行业务级别的...

    markdown-doctest:测试markdown文档中的所有代码!

    测试降价文档中的所有代码! 为什么在地球上? 作为一个开源开发人员,没有什么比用户打开一个问题通知您README示例已损坏更令人尴尬的了! 使用markdown-doctest ,您可以轻松知道示例代码实际上是可运行的。 ...

    在Python中结合doctest和Epydoc产生敏捷文档的一种方法.pdf

    3. doctest非常适合保持文档和代码的同步,因为代码注释中本身就包含了测试用例。 4. 测试用例可以与代码分离,独立存在于特定的文件中,便于管理。 5. 通过增强选项,doctest可以更灵活地匹配测试中的各种输出情况...

    doctest:Haskell的python doctest的实现

    Doctest:测试交互式Haskell示例doctest是一个小程序,用于检查。 它与相似,。安装可以从获得doctest 。 通过键入以下内容进行安装: cabal install doctest确保Cabal的bindir在您的PATH 。 在Linux上: export ...

    Python单元测试工具doctest和unittest使用解析

    doctest:一个简单的模块,为检查文档而设计,但也适合用来编写单元测试。 unittest:一个通用的测试框架。 一、使用doctest进行单元测试 创建文件mymath.py,内容 def square(x): ''' 计算平方并返回结果(下面...

    DocTest:用于测试文档中的Swift示例代码的实验工具

    DocTest是一款实验性的工具,专为测试文档中的Swift示例代码而设计。它提供了一种高效的方法,确保在编写或更新文档时,其中包含的代码片段是准确无误且可运行的。这对于维护高质量的开源项目或者内部软件文档至关...

    Python单元测试模块doctest的具体使用

    Python标准库中的`doctest`模块提供了一种简洁的方式来集成测试到代码的文档字符串中,使得测试和代码更加紧密地结合。以下将详细介绍`doctest`模块的使用方法和相关知识点。 首先,`doctest`模块的核心功能是扫描...

    JavaScript的测试框架Doctest.js.zip

    Doctest.js 是 JavaScript 的测试框架。 示例测试代码: function capitalize(words) { return words.replace(/\b[a-z]/g, function (m) { return m[0].toUpperCase(); }); } print(capitalize('some words'))...

    Python测试框架: 用Python测试框架简化测试

    zope.testing 包只支持 unittest 和 doctest 等传统 Python 测试风格,而不支持更现代的框架支持的简化风格。但是,它提供一个强大的分层系统,在这种系统中包含测试的目录可以依赖于通用的设置代码,设置代码为层...

    mod2doctest-0.1.0.zip

    这个库主要的功能是与Python的内置`doctest`模块相结合,用于测试和验证代码模块中的文档字符串(docstrings)。`doctest`模块是一个强大的工具,它能自动检查代码文档中嵌入的测试用例,确保代码的实际行为与文档所...

    doctest:最快的功能丰富的C ++ 11141720单头测试框架

    它与其他测试框架之间的主要区别在于它轻巧且不打扰: 无论是在还是写入方面,都非常精简编译时间即使在针对MSVC / GCC / Clang的警告级别上也不会产生任何警告提供一种使用标识符从二进制文件中删除所有与测试相关...

    jsdoctap:使用JSDoc示例和node-tap的doctest的测试运行器

    使用JSDoc示例和node-tap进行doctest的测试运行程序。 基于的辛勤工作和。 安装 npm i -D jsdoctap 用法 jsdoctap some-file.js 我建议将其添加到您的npm脚本中。 例子: { " scripts " : { " test " : " ...

    doctest-prop:允许在 doctest 中进行 QuickCheck 风格的属性测试

    这个包允许你在 doctest 中编写 QuickCheck 属性,使用在测试成功时保持沉默的函数,否则打印出测试输出。 要享受 Haskell 中的行为驱动开发,首先导入Test.DocTest.Prop ,并使用prop 、 propWith和unit编写就地...

    sbt-doctest:scala的doctest

    **sbt-doctest:Scala的测试工具** `sbt-doctest`是Scala开发中的一个非常有用的插件,它允许开发者在代码注释中编写测试用例,这些测试用例会在编译过程中自动运行,确保代码的正确性。这个工具极大地提高了代码的...

Global site tag (gtag.js) - Google Analytics