我即将开始一些基于Python的大型App Engine项目,我认为在进行单元测试策略之前,我应该先了解Stack Overflow的“人群智慧”。我有一个我想要使用的现有单元测试框架(基于unittest和自定义运行器和扩展),所以任何“重量级”/“侵入性”,例如nose,{{3 }},或webtest似乎不合适。在我的世界观中,关键的单元测试是极其轻巧和快速的,在非常短的时间内运行,所以我可以一直运行它们而不会破坏我的开发节奏(例如,对于不同的项目,我得到对于一个20K线项目有97%左右的覆盖率,需要几十次超快速测试,需要5-7秒,经过一段时间,对于一次典型的运行,总体来说 - 这就是我认为是一套体面的小型,快速单元 - 测试)。我当然会有更丰富/更重的测试,一直到硒或风车的集成测试,那是不我要问的问题;-) - 我对这个问题的关注(在我的大多数开发工作中;-)是小型,轻量级的单元测试,轻松且超级快速地覆盖我的代码,而不是更深层次的代码。
所以我认为我需要的是一组小型的,非常轻量级的各种关键App Engine子系统模拟 - 数据存储,内存缓存,请求/响应对象以及对webapp处理程序的调用,用户处理,邮件和& c,大致按此优先顺序排列。我还没有找到我正在寻找的东西,所以在我看来,我应该依赖gaeunit,就像我过去经常做的那样,这基本上意味着模拟给定的每个子系统测试和设置所有期望& c(强大,但每次都很多工作,对测试代码的内部非常敏感,即非常“白盒”y),或者滚动我自己的每个子系统的模拟(并做断言模拟子系统的状态作为单元测试的一部分)。后者似乎是可行的,考虑到GAE的Python端强大的“存根”架构...但我不敢相信我需要自己动手,即没有人已经编写了这样简单的模拟器! - )例如,对于数据存储区,看起来我需要的或多或少是“文件数据存储”存根,它已经是SDK的一部分,另外还有一种方法可以标记它只读和易于使用的访问器,用于断言数据存储的状态;依此类推,子系统逐个子系统 - 每个似乎都需要比现有的“存储”架构中“已经存在”的“仅仅更多一点”。
所以,在潜入并花费一两天宝贵的开发时间“滚动我自己”模拟GAE子系统进行单元测试之前,我想我会对SO人群进行双重检查,看看你们都在想什么这个...或者,如果已经有一些现有的开源软件集,我可以简单地重复使用(或者最小化调整! - ),而我在搜索中没有发现它! - )
编辑:澄清一下,如果我自己动手,我会计划在可行的情况下利用SDK提供的存根;但是例如,对于最初从文件读入但最后没有保存的数据存储区没有存根,所以我需要子类化并调整现有的数据存储区(这也没有提供特别方便的方法来对其进行断言) state - 与邮件服务存根相同,等等。这就是我所说的“滚动我自己” - 而不是“从头开始重写”! - )
编辑:“为什么不是GAEUnit” - GAEUnit很适合自己的用例,但运行dev_appserver并在我的浏览器中查看结果(甚至通过urllib.urlopen)绝对不是我的意思之后 - 我想使用一个完全自动化的设置,适合在现有的测试运行框架内运行,该框架基于扩展unittest,并且没有HTTP的方式(所述框架将“快速”测试定义为其中一个其他的东西没有套接字和最小的磁盘I / O - 我们模拟或模拟这些 - 所以通过gaeunit我做的不比“中等”测试更好+ +没有方便的方法为每个测试预填充数据存储区(并且没有OO结构到帮助定制事物。)
答案 0 :(得分:13)
您不需要编写自己的存根 - SDK包含它们,因为它们用于模拟生产API。并非所有这些都适合用于单元测试,但大多数都适用。查看this code,了解使用内置存根所需的设置/拆卸代码示例。
答案 1 :(得分:5)
NoseGAE是一个鼻子插件,通过自动为您设置开发环境和测试数据存储来支持单元测试。在dev_appserver上开发时非常有用。
答案 2 :(得分:4)
我使用GAEUnit作为我的Google App Engine应用程序,我对测试的速度非常满意。我喜欢GAEUnit的东西,我确信Webtest会这样做,就是它为测试所有内容的存根创建了自己的版本,让你的“实时”版本单独进行测试。
因此,当您运行GAETests时,您可能用于开发的数据存储区将保留原样。
答案 3 :(得分:3)
我还可以补充说Fixture在我的单元测试中非常有用。它允许您以声明性语法创建模型,并将其转换为可在测试中加载的存储实体。这样,您就可以在每个测试用例的开头使用相同的数据集!这样可以避免在每次测试开始时手动创建数据。以下是Fixture文档中的示例: 鉴于此模型:
from google.appengine.ext import db
class Entry(db.Model):
title = db.StringProperty()
body = db.TextProperty()
added_on = db.DateTimeProperty(auto_now_add=True)
您的灯具将如下所示:
from fixture import DataSet
class EntryData(DataSet):
class great_monday:
title = "Monday Was Great"
body = """\
Monday was the best day ever.
"""
但请注意,我遇到了以下问题: 1. This bug,但附带的补丁可以解决它。 2.数据存储区不是 - 在测试用例之间默认重置。所以我使用它强制重置每个测试用例:
class TycoonTest(unittest.TestCase):
def setUp(self):
# Clear out the datastore before starting the test.
apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map['datastore_v3'].Clear()
self.data = self.load_data()
self.data.setup()
os.environ['SERVER_NAME'] = "dev_appserver"
self.after_setUp()
def load_data(self):
return datafixture.data(*dset.__all__)
def after_setUp(self):
""" After setup
"""
pass
def tearDown(self):
# Teardown data.
try:
self.data.teardown()
except:
pass
答案 4 :(得分:1)
SDK 1.4.3 Testbed API为本地集成测试提供了简单的存根库配置。
答案 5 :(得分:0)
由于1.3.1 version of SDK有内置unit test framework。
现在只是Java,但我觉得:
这个框架的作者也是如此 - Max Ross并且他在他的I / O演示中明确告诉我们"Testing techniques for Google App Engine"
有没有人对此主题有任何更新?