代码之家  ›  专栏  ›  技术社区  ›  Alex Martelli

您在AppEngine上使用了什么方法进行轻量级Python单元测试?

  •  38
  • Alex Martelli  · 技术社区  · 16 年前

    我即将开始一些大型的基于Python的应用程序引擎项目,我认为我应该先检查Stack Overflow的“群体智慧”,然后再致力于单元测试策略。我有一个现有的单元测试框架(基于 unittest 使用我想要使用的自定义跑步者和扩展),所以任何“重磅”/“侵入性”的东西,例如 nose , webtest gaeunit 似乎不太合适。在我的worldview中,关键的单元测试是非常轻量级和快速的,它们在非常短的时间内运行,因此我可以一直反复运行它们,而不会打破我的开发节奏(例如,对于一个不同的项目,我得到一个20K线路项目的97%个覆盖率,几十个超快速测试,花费5-7秒,经过一段时间,对于一个典型的运行,总体来说,这就是我认为的一套像样的小的、快速的单元测试)。.当然,我也会进行更丰富/更繁重的测试,一直到使用selenium或windmill进行集成测试,这很简单 我在问什么;-)——我在这个问题上(以及在我的大部分开发工作中;-)的重点是轻量级的小型单元测试,它可以轻松、超快速地覆盖我的代码,而不是更深层次的测试。

    因此,我认为我需要的基本上是对各种关键应用程序引擎子系统的一组小型、非常轻量级的模拟——数据存储、memcache、请求/响应对象和对webapp处理程序的调用、用户处理、邮件等;c、 大致按照这个优先顺序。我还没有找到我要找的东西,所以在我看来,我要么依赖 mox ,就像我过去经常做的那样,这基本上意味着模拟给定测试中使用的每个子系统,并设置所有期望值&c(很强,但每次都要做很多工作,并且对被测试代码的内部非常敏感,即非常“白盒”y),或者对每个子系统进行我自己的模拟(并作为单元测试的一部分对模拟子系统的状态进行断言)。鉴于GAE的Python端强大的“存根”架构,后者似乎是可行的。。。但我不敢相信我需要自己动手,也就是说,还没有人编写过如此简单的模拟器例如,对于数据存储,我需要的似乎是或多或少的“文件上的数据存储”存根,它已经是SDK的一部分,加上一种将其标记为只读和易于使用的访问器的方法,用于断言数据存储的状态;以此类推,一个子系统一个子系统——每个子系统似乎都需要比SDK中已有的“位于现有“存根”体系结构之上”的“稍微多一点”。

    因此,在投入一两天宝贵的开发时间“滚动我自己的”GAE子系统模拟以进行单元测试之前,我想我应该与So人员再次核实一下,看看大家对此有何看法。。。或者,如果已经有一些现有的开源模拟器,我可以简单地重用(或者至少调整一下!),但我在搜索中没有发现!)

    编辑 :为了澄清,如果我确实推出自己的,我确实计划在可行的情况下利用SDK提供的存根;但是,例如,数据存储没有存根,它最初是从文件中读取的,但最后没有保存,因此我需要对现有的存根进行子类化和调整(这也没有提供特别方便的方法来对其状态进行断言——邮件服务存根也是如此,等等)。这就是我所说的“自己翻滚”——而不是“从头开始重写”!-)

    :“为什么不使用GAEUnit”--GAEUnit对于它自己的用例来说很好,但是运行dev_appserver并在我的浏览器中查看结果(甚至通过urllib.urlopen)绝对不是我想要的--我想使用一个完全自动化的设置,适合在基于扩展unittest的现有测试运行框架中运行,并且不使用HTTP(上述框架将“快速”测试定义为一种不进行套接字和最小磁盘I/O的测试——我们模拟或模拟这些测试——因此通过gaeunit,我只能进行“中等”测试)+没有方便的方法为每个测试预填充数据存储(也没有OO结构来帮助定制)。

    6 回复  |  直到 16 年前
        1
  •  13
  •   Nick Johnson    16 年前

    您不需要编写自己的存根-SDK包括它们,因为它们是用来模拟生产API的。并不是所有这些都适合在单元测试中使用,但大多数都适合。退房 this code 例如,安装/拆卸代码需要使用内置存根。

        2
  •  5
  •   Hai-Anh Trinh    16 年前
        3
  •  4
  •   AutomatedTester    16 年前

    因此,您可能用于开发的数据存储在运行gaetest时将保持原样。

        4
  •  3
  •   mahmoud    15 年前

    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 ,但附带的补丁确实解决了这一问题。

    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
    
        5
  •  1
  •   Till Ulen    13 年前

    SDK 1.4.3 Testbed API 为本地集成测试提供简单的存根库配置。

        6
  •  0
  •   keiw    15 年前

    自从 1.3.1 version of SDK unit test framework .

    1. 这与您在问题中谈论的内容基本相同(甚至更多——例如在云中运行测试)
    2. 使用SDK在Python上移植\实现同样的功能是完全可能的

    Max Ross "Testing techniques for Google App Engine"

    有人对这个话题有任何更新吗?