Selenium私房菜系列4 -- Selenium IDE的使用

前面说过,Selenium IDE是Firefox的一个插件,是可以进行脚本录制以及案例转换,所以Selenium IDE+Firebug会成为你日后写测试案例的两大助手(IE下可以使用Selenium Core+IEDevelperToolBar)。 Selenium IDE下载: http://seleniumhq.org/download/ Firebug下载: https://addons.mozilla.org/firefox/addon/1843 下面将演示Selenium的使用 : 1.安装Selenium IDE,Firebug。 2.启动Selenium IDE: IDE启动后,弹出如下对话框: 上图标明了一些Selenium IDE的主要功能。其中,由Command,Target,Value组成的表格就是脚本,每个脚本都是由一条一条的Action(行为)组成,而每个Action又由(Command,Target,Value)三者组成。Command就是上文 《API参考手册》 提到的内容,Target指的是Web中的某个对象,比如:文字,输入框等等,如果选取对象呢?呵呵,这里就用到了XPath,不熟悉可以参考 《XPath的使用》 ,而Value就是这个对象的值。 3.脚本的录制及运行 当弹出上面的IDE窗口后,我们就可以开始Selenium的脚本录制了,右上角有个红色的圆点,当它下按时(如上图)就表示IDE正在进行脚本录制。OK,开始录制,录制的时候,直接操作Firefox浏览器窗口就可以了,IDE会自动记录你的操作的,下面我演示一个例子: 上图例子中,我的操作步骤如下: (1).在地址栏输入: http://www.baidu.com/ (2).登陆百度首页后,在查询框输入 hyddd 。 (3).按 百度一下 按钮 (4).进入搜索结果页面后,右键单击第一条记录(即:hyddd - 博客园),在右键弹出菜单中,单击 Verify TestPersent hyddd - 博客园 。 (5).单击第一条记录(即:进入hyddd - 博客园) (6).Firefox弹出一个新Tab页面,并进入了我的博客。 OK,现在看看我们的Selenium IDE录制的结果吧: 上图中,中间的表格就是录制的结果,你可以按 运行脚本 重新回放脚本看看,值得注意的是,在运行时,Firefox可能会认为脚本中最后一个操作(即:步骤6)为非法弹出框,浏览器会自动阻止其弹出,这个需要设置一下Firefox,具体位置是:Firefox- Menubar- Tools- options- content- Block pop-up Window,你可以把钩去掉或者在Exceptions里面添加相应的网址。 恩,到此为止,脚本录制圆满完成: 在运行脚本后,你会发现IDE表格的颜色发生了变化,运行前,脚本表格为白色,成功运行完毕后,表格为青色,其中还分为深青色和浅青色两种,浅青色表示:动作成功,如:打开网页成功,点击按钮成功等等,而深青色表示:判断正确,如: hyddd - 博客园 这段文字在页面中存在等等。 看完正确,现在我们看看出错时的情况吧。 出错时,表格可能会出现两种颜色,一种是浅粉红色,一种是深粉红色。浅粉红色表示判断结果为false,这种情况案例还是会继续执行下去,判断的失败不会影响案例的运行,深粉红色表示动作失败,如:没有找到按钮等(如上图),这种情况下案例会停止运行。 4.Selenium IDE其他的重要功能 本文开始时提到了,Selenium IDE还有一个重要的功能就是把脚本的转换,一起看看吧: Selenium IDE可以把HTML的脚本转为C#,JAVA等等其他语言的脚本,为我们日后写Selenium RC的测试案例提供了极大的方便。 ...

阅读全文 »

Selenium私房菜系列 -- XPath的使用

在编写Selenium案例时,少不免是要用到XPath的,现在外面关于XPath使用的参考资料很多,下面我直接转一篇关于XPath使用的文档。如果对XPath不熟悉请参考下文,你不需要去百度/Google搜索关于XPath的资料,因为下面的内容已经足够你写测试时使用,如果你已熟悉XPath,本章大可忽略跳过。 xpath的语法 ( 转载自 : http://www.cnblogs.com/jianjialin/archive/2009/02/01/1382056.html XPath 是XML的查询语言,和SQL的角色很类似。以下面XML为例,介绍XPath 的语法。 ? xml version= 1.0 encoding= ISO-8859-1 ? catalog cd country = USA title Empire Burlesque / title artist Bob Dylan / artist price 10.90 / price / cd cd country = UK title Hide your heart / title artist Bonnie Tyler / artist price 9.90 / price / cd cd country = USA title Greatest Hits / title artist Dolly Parton / artist price 9.90 / price / cd / catalog / catalog 定位节点 XML是树状结构,类似档案系统内数据夹的结构,XPath也类似档案系统的路径命名方式。不过XPath 是一种模式(Pattern),可以选出 XML档案中,路径符合某个模式的所有节点出来。例如要选catalog底下的cd中所有price元素可以用: /catalog/cd/price 如果XPath的开头是一个斜线(/)代表这是绝对路径。如果开头是两个斜线(//)表示文件中所有符合模式的元素都会被选出来,即使是处于树中不同的层级也会被选出来。以下的语法会选出文件中所有叫做cd的元素(在树中的任何层级都会被选出来): //cd 选择未知的元素 使用星号(Wildcards,*)可以选择未知的元素。下面这个语法会选出/catalog/cd 的所有子元素: /catalog/cd/* 以下的语法会选出所有catalog的子元素中,包含有price作为子元素的元素。 /catalog/*/price 以下的语法会选出有两层父节点,叫做price的所有元素。 /*/*/price 以下的语法会选择出文件中的所有元素。 //* 要注意的是,想要存取不分层级的元素,XPath语法必须以两个斜线开头(//),想要存取未知元素才用星号(*),星号只能代表未知名称的元素,不能代表未知层级的元素。 选择分支 使用中括号可以选择分支。以下的语法从catalog的子元素中取出第一个叫做cd的元素。XPath的定义中没有第0元素这种东西。 /catalog/cd[1] 以下语法选择catalog中的最后一个cd元素:(XPathj并没有定义 first() 这种函式喔,用上例的 [1]就可以取出第一个元素。 /catalog/cd[last()] 以下语法选出含有price子元素的所有/catalog/cd元素。 /catalog/cd[price] 以下语法选出price元素的值等于10.90的所有/catalog/cd元素 /catalog/cd[price=10.90] 以下语法选出price元素的值等于10.90的所有/catalog/cd元素 的price元素 /catalog/cd[price=10.90]/price 选择一个以上的路径 使用Or操作数(|)就可以选择一个以上的路径。例如: /catalog/cd/title | catalog/cd/artist 选择所有title以及artist元素 //title | //artist 选择所有title以及artist以及price元素 //title | //artist | //price 选择属性 在XPath中,除了选择元素以外,也可以选择属性。属性都是以@开头。例如选择文件中所有叫做country的属性。 //@country 选择所有含有country这个属性的cd元素: //cd[@country] 以下语法选择出含有属性的所有cd元素 //cd[@*] 以下语法选择出country属性值为UK的cd元 //cd[@country='UK'] 选择多个属性 //cd[@country='UK'][@name='hyddd'] ...

阅读全文 »

Selenium私房菜系列 -- Selenium简介

一.Selenium是什么? Selenium是ThroughtWorks公司一个强大的开源Web功能测试工具系列,本系列现在主要包括以下4款: 1.Selenium Core:支持DHTML的测试案例(效果类似数据驱动测试),它是Selenium IDE和Selenium RC的引擎。 2.Selenium IDE:FireFox的一个插件,支持脚本录制。 3.Selenium RC:Selenium Remote Control。后续的系列文章我会主要针对Selenium RC展开介绍。 4.Selenium Grid:允许同时并行地、在不同的环境上运行多个测试任务,极大地加快Web应用的功能测试。 二.选择合适的Selenium工具 既然Selenium工具有4款这么多,那到底如何选择呢??我从 Selenium官网 这里找了一个表: Selenium IDE Selenium Remote Control Selenium Core Selenium Core HTA 浏览器支持 仅Firefox 很多 所有 仅IE 需要远程安装 否 否 是 否 支持 HTTPS/SSL 是 是* 是 是 支持跨域 是 是* 否 是 需要Java 否 是 否 否 将测试结果保存到磁盘 是 是 否 是 多语言支持 仅Selenese 很多 仅Selenese 仅Selenese 这里没有介绍Selenium Grid,但介绍了另外一个Selenium Core HTA,Selenium Core HTA其实是Selenium Core的额外模式,你只要Selenium Core配置稍加修改,即为HTA模式,Selenium Core HTA可以在IE最高安全等级(特权)下工作,这意味着它仅能在IE下工作,由于限制较大,下面将排除对Selenium Core HTA的讨论。 1.浏览器支持 : (1).Selenium IDE仅可以在Firefox中工作。 (2).Selenium Remote Control支持很多浏览器,包括最常用的:firefox,ie,safari等N款浏览器。 (3).Selenium Core支持的浏览器是最广的,这点和它的实现有关。作为IDE和RC的引擎,Selenium Core几乎可以在任何浏览器中工作。 2.需要远程安装 :是否需要在被测网站的服务端安装? 这里只有Selenium Core需要,这是出于同源策略的原因。这也是Selenium Core一个很大的限制,试问,如果你要测试Google.com,还得在google的服务器上装一个Selenium Core,那是多搞笑的一件事。 而Selenium IDE和Selenium Core HTA不会被同源策略所限制,因为他们对浏览器扩展了。 Selenium RC提供一个代码服务器来保证Selenium JS文件看似来自相同的远程服务器,从而符合同源策略;代理服务器欺骗浏览器,让它认为这里的确有像 http://www.google.com/selenium/ 这样的目录。 3.支持HTTPS/SSL : 这里不说了,都支持。Selenium RC在 是 后面加*因为它是在最近版本支持的,仅此而已。 4.需要Java :准确的说是需要JRE 这项只有Selenium RC需要,上面2中所说的 代理服务器 是一个Java程序,需在跑测试案例前启动。 5.将测试结果保存到磁盘 只有Selenium Core不能将任何测试结果写到磁盘上(因为它是用javascript写的,它不允许向磁盘写数据),其解决方案是当然你可以将测试结果发送到另外一台服务器保存。这也是Selenium Core的一大限制。 6.多语言支持 (1).Selenium IDE仅支持Selenium语言。 (2).Selenium RC支持很多语言,如:C#,Java,Python,Ruby等。 (3).Selenium Core也是仅支持Selenium语言。 Selenium语言的测试案例如下: 它的优点是:简单,用(Command,Target,Value)三种元素组成一个行为,并且有辅助录制脚本工具(如:Firefox IDE,Selenium Core等),不懂程序的测试人员都可以轻松地编写测试案例。 它的缺点是:Selenese有一些严格的限制:它没有条件(没有 if 表达式),并且它没有循环(没有 For 表达式)。这会使编写复杂的测试变得困难甚至不可能。 OK,现在我们来研究下到底该使用哪款工具开展测试! (1).Selenium IDE支持并且只支持Firefox浏览器,支持的浏览器太少,而依附于Firefox也不便于日后开展自动化测试,但是,它的录制快捷好用!并且有代码转换功能,可以把Selenium语言测试案例转为C#,Java等语言的测试案例,我建议使用Selenium IDE + FireBug进行测试案例的编写,然后转为其他语言的测试案例后,再调用Selenium RC运行测试案例。 (2).Selenium Core,它的优点是编写测试案例简单,并且支持绝大多数的浏览器,但缺点也同样明显,Selenium Core需要远程安装,Selenese语言也限制了复杂案例的可能性,并且没有良好的外部扩展,这是些都会是致命的问题。因为一个款测试工具不可能100%满足你测试需求的,当它不能满足你测试需求时候,它必须有一个扩展机制可以让你可以使用其他的方式满足你需求,否则这款测试软件即使功能强大,也请三思慎用,否则当投入大量资源后才发现某些问题不能解决,那时候已经晚了,这是我的切身体会。 (3).Selenium RC是我推荐使用的工具,它支持很多浏览器,可以使用C#,Java等语言编写测试案例,易于维护,同时提供了很好的扩展性,所以后续的文档我会以Selenium RC作为默认的测试工具。 ...

阅读全文 »

Selenium私房菜系列--前言

前言 在这段期间,我一直在找关于服务器的端测试方案,自动化工具等等,无意间我发现了Selenium 这个工具。在试用一段时间后,觉得 Selenium 确实是一个很不错的 Web 测试工具。在和强大的 QTP 比较后,我最后还是选择了使用 Selenium ,主要的原因 是工具使用灵活,简单,并且完全满足我的要求 。而QTP 虽然强大,但它的使用让我觉得非常繁琐,而调试功能也让我郁闷 ...... 鉴于种种这样的原因,我最后选择了 Selenium 。 本系列文章主要是总结我在前一段时间了解到的关于Selenium 的一些知识。 QTP VS Selenium 下面我想先稍微讨论一下这两个工具, 我主要从功能和文档资料这两方面对比QTP 和 Selenium 。 功能 从Web 测试的角度,两个工具都能满足正常的测试需求,这个你无需怀疑!但 QTP 更强大些,因为: 1. 它是商业软件,只要你有钱,什么都可以有。 2. 它支持对操作Windows 窗口,当你要从 Web 上下载一些东西,自然此时就会弹出一个 下载框 ,由于那个框框是 Windows 窗口, Selenium 是处理不了的,所以必须通过第三方的脚本处理。 文档和参考资料资料 如果你这方面的新手,当你用QTP/Selenium 时,相信书和文档是你第一样会找的东西。在这样面, QTP 使用在中国使用还是蛮广泛的,资料和书籍也相当丰富,而 Selenium 的资料就相对比较少一些,找资料最好的地方就是官方论坛。 为什么用Selenium 既然上面两项都是QTP 优胜一些,为什么我们还是用 Selenium ,因为: 1. Selenium 使用灵活,简单,写出的测试案例非常简洁,优美,也易于维护。 2. Selenium RC 支持用多种语言编写测试案例,你可以用 VS2008 写测试案例了 : 。 3. 如果你有一个测试平台,你会发现把QTP 整合到平台是很麻烦的事情。 4. ...... 如果以上Selenium 的优点不能打动你,又或者你是测试新手,对测试经验不多,对编程也不熟悉,那么你还是继续使用 QTP 吧,不过相信有一天,你会开始尝试 Selenium 的。 Selenium 名字的来源 在这里,我还想说一下关于Selenium 名字的来源,很有意思的 : : Selenium 的中文名为 硒 ,是一种化学元素的名字,它 对 汞 (Mercury )有天然的解毒作用,实验表明汞暴露水平越高,硒对汞毒性的拮抗作用越明显,所以说硒是汞的克星。大家应该知道 Mercury 测试工具系 列吧( QTP , QC , LR , WR... ),他们功能强大,但却价格不菲,大家对此又爱又恨!故 thoughtworks 特意把他们的 Web 开源测试工具命 名为 Selenium ,以此帮助大家脱离汞毒。 ...

阅读全文 »

python中的异常

python中的异常 异常是指程序中的例外,违例情况。异常机制是指程序出现错误后,程序的处理方法。当出现错误后,程序的执行流程发生改变,程序的控制权转移到异常处理。 Exception类是常用的异常类,该类包括StandardError,StopIteration, GeneratorExit, Warning等异常类。 StandardError类是python中的错误异常,如果程序上出现逻辑错误, 将引发该异常。StandardError类是所有内敛异常的基类,放置在默认的命名空间中,因此使用IOEroor, EOFError, ImportError等类,不需要导入exception模块。 StopIteration类判断循环是否执行到尾部,如果循环到尾部,则抛出该异常。 GeneratorExit类是由Generator函数引发的异常,当调用close()时引发该异常。 Warning类表示程序中的代码引起的警告。 python中的异常使用继承结构创建,可以在异常处理程序中捕获基类异常,也可以捕获各种子类异常,python中使用try...except语句捕获异常,异常子句定义在try子句后面。 try...except的使用方法 try...except用于处理问题语句,捕获可能出现的异常。try子句中的代码块放置可能出现异常的语句,except子句中的代码块处理异常。 演示try...except语句捕获IOError异常 try: file( hello.txt , r ) #如果文件不存在,引发异常 print 读文件 except IOError: #捕获IO异常 print 文件不存在 except: #其它异常 print 程序异常 python与Java的异常处理模式相似,异常处理语句也可以嵌套,演示如下: try: s = hello try: print s[0] + s[1] print s[0] - s[1] except TypeError: print 字符串不支持减法运算 except: print 异常 如果外层try子句中的代码引发异常,程序将直接跳转到外层try对应的except子句,而内部的try子句将不会被执行。 try...finally的使用方法 try...except后还可以添加一个finally子句。无论异常是否发生,finally子句都会被执行。所有的finally子句通常用于关闭因异常而不能释放的系统资源。 try: f = open( hello.txt , r ) try: print f.read(5) except: print 读文件异常 finally: print 释放资源 f.close() except IOError: print 文件不存在 使用raise抛出异常 当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。 演示raise用法 try: s = None if s is None: print s 是空对象 raise NameError #如果引发NameError异常,后面的代码将不能执行 print len(s) except TypeError: print 空对象没有长度 自定义异常 python允许程序员自定义异常,用于描述python中没有涉及的异常情况,自定义异常必须继承Exception类,自定义异常按照命名规范以 Error 结尾,显示地告诉程序员这是 异常。自定义异常使用raise语句引发,而且只能通过人工方式触发。 from __future__ import division class DivisionException(Exception): def __init__(self, x, y): Exception.__init__ (self, x, y) #调用基类的__init__进行初始化 self.x = x self.y = y if __name__ == __main__ : try: x = 3 y = 2 if x % y 0: #如果大于0, 则不能被初始化,抛出异常 print x/y raise DivisionException(x, y) except DivisionException,div: #div 表示DivisionException的实例对象 print DivisionExcetion: x/y = %.2f % (div.x/div.y) assert语句的使用 assert语句用于检测某个条件表达式是否为真。assert语句又称为断言语句,即assert认为检测的表达式永远为真,if语句中的条件判断都可以使用assert语句检测。 ...

阅读全文 »

python常用的时间(time)的方法

我们先导入必须用到的一个module import time 设置一个时间的格式,下面会用到 ISOTIMEFORMAT= %Y-%m-%d %X 看一下当前的时间,和其他很多语言相似这是从epoch(1970 年 1 月 1 日 00:00:00)开始到当前的秒数。 time.time() 1180759620.859 上面的看不懂,换个格式来看看 time.localtime() (2007, 6, 2, 12, 47, 7, 5, 153, 0) localtime返回tuple格式的时间,有一个和它类似的函数叫gmtime(),2个函数的差别是时区,gmtime()返回的是0时区的值,localtime返回的是当前时区的值。 time.strftime( ISOTIMEFORMAT, time.localtime() ) 2007-06-02 12:54:29 用上我们的时间格式定义了,使用strftime对时间做一个转换,如果取现在的时间,time.localtime() 可以不用。 time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) 2007-06-02 12:54:31 time.strftime( ISOTIMEFORMAT, time.gmtime( time.time() ) ) 2007-06-02 04:55:02 上面展示了gmtime和localtime的区别。 查看时区用 time.timezone -28800 上面的值是一个秒值,是当前时区和0时区相差的描述,-28800=-8*3600,即为东八区。 帖几个简单的函数 def ISOString2Time( s ): convert a ISO format time to second from:2006-04-12 16:46:40 to:23123123 把一个时间转化为秒 return time.strptime( s, ISOTIMEFORMAT ) def Time2ISOString( s ): convert second to a ISO format time from: 23123123 to: 2006-04-12 16:46:40 把给定的秒转化为定义的格式 return time.strftime( ISOTIMEFORMAT, time.localtime( float( s ) ) ) def dateplustime( d, t ): d=2006-04-12 16:46:40 t=2小时 return 2006-04-12 18:46:40 计算一个日期相差多少秒的日期,time2sec是另外一个函数,可以处理,3天,13分钟,10小时等字符串,回头再来写这个,需要结合正则表达式。 return Time2ISOString( time.mktime( ISOString2Time( d ) )+time2sec( t ) ) def dateMinDate( d1, d2 ): minus to iso format date,return seconds 计算2个时间相差多少秒 d1=ISOString2Time( d1 ) d2=ISOString2Time( d2 ) return time.mktime( d1 )-time.mktime( d2 ) ...

阅读全文 »

Python 入门指南

注意: 目前已经用 Sphinx 重新整理一次,可以直接访问 http://www.pythondoc.com/pythontutorial3/index.html 或者 http://www.pythondoc.com/ The Python Tutorial Python 入门指南 Release: 3.1 Date: September 05, 2009 Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms. Python是一门简单易学且功能强大的编程语言。 它拥有高效的高级数据结构,并且能够用简单而又高效的方式进行面向对象编程。 Python优雅的语法和动态类型,再结合它的解释性,使其在大多数平台的许多领域成为编写脚本或开发应用程序的理想语言。 The Python interpreter and the extensive standard library are freely available in source or binary form for all major platforms from the Python Web site, http://www.python.org/ , and may be freely distributed. The same site also contains distributions of and pointers to many free third party Python modules, programs and tools, and additional documentation. 你可以自由的从Python官方点,http://www.python.org,以源代码或二进制形式获取Python解释器及其标准扩展库,并可以自由的分发。 此站点同时也提供了大量的第三方Python模块、程序和工具,及其附加文档。 The Python interpreter is easily extended with new functions and data types implemented in C or C++ (or other languages callable from C). Python is also suitable as an extension language for customizable applications. 你可以很容易的使用C或C++(其他可以通过C调用的语言)为Python解释器扩展新函数和数据类型。 Python还可以被用作定制应用程式的一门扩展语言。 This tutorial introduces the reader informally to the basic concepts and features of the Python language and system. It helps to have a Python interpreter handy for hands-on experience, but all examples are self-contained, so the tutorial can be read off-line as well. 本手册非正式的向读者介绍了Python语言及其体系相关的基本知识与概念。 在学习实践中结合使用Python解释器是很有帮助的,不过所有的例子都是完整的,所以本手册亦可离线阅读。 For a description of standard objects and modules, see the Python Library Reference document. The Python Reference Manual gives a more formal definition of the language. To write extensions in C or C++, read Extending and Embedding the Python Interpreter and Python/C API Reference. There are also several books covering Python in depth. 如果需要了解相关标准库或对象的详细介绍,请查阅Python库参考文档。 Python参考手册提供了更多语言相关的正式说明。 如果想要使用C或C++编写扩展,请查阅Python解释器扩展和集成章节或Python/C API参考手册。 当然也可阅读一些深入介绍Python知识的图书。 This tutorial does not attempt to be comprehensive and cover every single feature, or even every commonly used feature. Instead, it introduces many of Python’s most noteworthy features, and will give you a good idea of the language’s flavor and style. After reading it, you will be able to read and write Python modules and programs, and you will be ready to learn more about the various Python library modules described in the Python Library Reference. 本手册不会尝试涵盖Python的全部知识和每个特性,甚至不会涵盖所有常用的特性。 相反的,它介绍了Python中许多最引人瞩目的特性,并且会给你一个关于语言特色和风格的认识。 读完之后,你将能够阅读和编写Python模块或程序,并为以后使用Python库参考手册继续学习诸多Python模块库做好准备。 The Glossary is also worth going through. 1. Whetting Your Appetite Appetitle 开胃菜 2. Using the ...

阅读全文 »

Twisted Web 代码示例

twisted.web.client getpage.py - 使用twisted.web.client.getPage 下载页面. dlpage.py -在下载页面过程中增加一个回调函数到twisted.web.client.downloadPage 用来显示错误信息 XML-RPC xmlrpc.py XML-RPC 服务器的几个方法 包括 echoing, faulting, returning deferreds 以及 failed deferreds xmlrpcclient.py - 使用 twisted.web.xmlrpc.Proxy来调用远程XML-RPC方法. advogato.py 使用twisted.web.xmlrpc添加日志到advogato.org,需要一个advogato.org帐号. 虚拟主机和代理 rootscript.py twisted.web.vhost.NameVirtualHost的例子 web.py 使用twisted.web.vhost.VHostMonsterResource作为反向代理处理某些特定文件. proxy.py -使用twisted.web.proxy把任何http请求通过代理端口转发到指定网站 hello.rpy.py - 使用twisted.web.static创建一个静态资源服务 fortune.rpy.py - 创建一个返回服务器运行进程输出的资源 l j.rpy.py - 使用twisted.web.microdom,twisted.web.domhelpers和回调链来提取显示一个LiveJournal用户的RSS页面. vhost.rpy.py - 创建一个twisted.web.vhost.VHostMonsterResource资源 report.rpy.py - 显示一个资源的各种属性,包括路径,主机和端口. users.rpy.py - 使用 twisted.web.distrib 发布一个 社区网站 的用户目录 simple.rtl 使用 twisted.web.resource.ResourceTemplate的模板示例 杂项 webguard.py -使用twisted.cred 来对twisted.web进行验证防止未授权的用户访问. silly-web.py - 使用wisted.web.distrib and twisted.spread.pb发布一个最基本的主从模型的分布式网站. google.py - 使用twisted.web.google获取我的手气不错的搜索页 soap.py 使用 twisted.web.soap 发布SOAP方法. 来源: http://twistedmatrix.com/documents/current/web/examples/#auto0 ...

阅读全文 »

Google 是如何做代码审查的

在上一篇文章中提到过,我已经不在Google工作了。我还没有想清楚应该去哪里 有两三个非常好的工作机会摆在我面前。因为在这段做决定时间里,我不再受雇于任何人,我想可以写一些专业性的东西,一些很有趣,但也会在同事和管理工作中导致关系紧张的东西。 Google是一个非常优秀的公司。他们做出了很多令人称赞的东西 既是公司外部,人们可以看到的东西,也是公司内部。有一些在公司内部并不属于保密的事情,在外部并没有给予足够广泛的讨论。这就是我今天要说的。 让Google的程序如此优秀的一个最重要的事情看起来是非常的简单:代码审查。并不是只有Google做这个事情 代码审查已经被广泛的认可为一种非常好的做法,很多人都在这样做。但我还没有看到第二家这样大的公司能把这种事情运用的如此普遍。在Google, 没有程序 ,任何产品、任何项目的程序代码,可以在没有经过有效的代码审查前提交到代码库里的。 所有人 都要经过代码审查。并且很正规的:这种事情应该成为任何重要的软件开发工作中一个基本制度。并不单指产品程序 所有东西。它不需要很多的工作,但它的效果是巨大的。 从代码审查里能得到什么? 很显然:在代码提交前,用第二群眼睛检查一遍,防止bug混入。这是对其最常见的理解,是对代码审查的好处的最广泛的认识。但是,依我的经验来看,这反倒是它 最不重要 的一点。人们确实在代码审查中找到了bug。可是,这些在代码审查中能发现的绝大部分bug,很显然,都是微不足道的bug,程序的作者花几分钟的时间就能发现它们。真正需要花时间去发现的bug不是在代码审查里能找到的。 代码审查的最大的功用是纯社会性的。如果你在编程,而且 知道 将会有同事检查你的代码,你编程态度就完全不一样了。你写出的代码将更加整洁,有更好的注释,更好的程序结构 因为你 知道 ,那个你很在意的人将会查看你的程序。没有代码审查,你知道人们最终还是会看你的程序。但这种事情不是立即发生的事,它不会给你带来同等的紧迫感,它不会给你相同的个人评判的那种感受。 还有一个非常重要的好处。代码审查能 传播知识 。在很多的开发团队里,经常每一个人负责一个核心模块,每个人都只关注他自己的那个模块。除非是同事的模块影响了自己的程序,他们从不相互交流。这种情况的后果是,每个模块只有一个人熟悉里面的代码。如果这个人休假或 但愿不是 辞职了,其他人则束手无策。通过代码审查,至少会有两个人熟悉这些程序 作者,以及审查者。审查者并不能像程序的作者一样对程序十分了解 但他会熟悉程序的设计和架构,这是极其重要的。 当然,没有什么事情能简单的做下来的。依我的经验,在你能正确的进行代码审查前,你需要花时间锻炼学习。我发现人们在代码审查时经常会犯一些错误,导致不少麻烦 尤其在一些缺乏经验的审查者中经常的出现,他们给了人们一个很遭的代码审查的体验,成为了人们接受代码审查制度的一个障碍。 最重要的一个原则:代码审查用意是在代码提交前找到其中的问题 你要发现是它的 正确 。在代码审查中最常犯的错误 几乎每个新手都会犯的错误 是,审查者根据自己的编程习惯来评判别人的代码。 对于一个问题,通常我们能找出十几种方法去解决。对于一种解决方案,我们能有百万种编码方案来实现它。作为一个审查者,你的任务不是来确保被审查的代码都采用的是你的编码风格 因为它不可能跟你写的一样。作为一段代码的审查者的任务是确保由作者自己写出的代码是正确的。一旦这个原则被打破,你最终将会倍感折磨,深受挫折 这可不是我们想要的结果。 问题在于,这种错误是如此的普遍而易犯。如果你是个程序员,当你遇到一个问题,你能想到一种解决方案 你就把你想到的方案作为标准答案。但事情不是这样的 作为一个好的审查者,你需要明白这个道理。 代码审查的第二个易犯的毛病是,人们觉得有压力,感觉非要说点什么才好。你知道作者用了大量的时间和精力来实现这些程序 不该说点什么吗? 不,你不需要。 只说一句 哇,不错呀 ,任何时候都不会不合适。如果你总是力图找出一点什么东西来批评,你这样做的结果只会损害自己的威望。当你不厌其烦的找出一些东西来,只是为了说些什么,被审查人就会知道,你说这些话只是为了填补寂静。你的评论将不再被人重视。 第三是速度。你不能匆匆忙忙的进行一次代码审查 但你也要能迅速的完成。你的同伴在等你。如果你和你的同事并不想花太多时间进行代码复查,你们很快的完成,那被审查者会觉得很沮丧,这种代码审查带来的只有失望的感觉。就好象是打搅了大家,使大家放下手头的工作来进行审查。事情不该是这样。你并不需要推掉手头上的任何事情来做代码审查。但如果中途耽误了几个小时,你中间还要休息一会,喝杯茶,冲个澡,或谈会儿闲话。当你回到审查现场,你可以继续下去,把事情做完。如果你真是这样,我想没有愿意在那干等着你。 ...

阅读全文 »

python challenge 33解题总结

网页注释中提示: !--If you are blinded by the light, remove its power, with its might. Then from the ashes, fair and square, another truth at you will glare.-- python challenge 33网址: www.pythonchallenge.com/pc/rock/beer.html 注意到图像名称是beer1.jpg,看看 http://www.pythonchallenge.com/pc/rock/beer2.jpg 图上提示 no, png,看看 http://www.pythonchallenge.com/pc/rock/beer2.png 好像是个有个x的灰度杂波图 查看图片信息(通过img.getcolors()) 可知,图像有66种颜色: [(1532, 1), (232, 2), (963, 7), (189, 8), (724, 13), (329, 14), (549, 19), (243, 20), (144, 25), (424, 26), (119, 31), (328, 32), (126, 37), (339, 38), (126, 43), (357, 44), (107, 49), (225, 50), (79, 55), (609, 56), (181, 61), (356, 62), (70, 67), (298, 68), (23, 73), (164, 74), (26, 79), (354, 80), (47, 85), (341, 86), (139, 91), (257, 92), (104, 97), (505, 98), (192, 103), (224, 104), (114, 109), (310, 110), (32, 115), (183, 116), (238, 121), (198, 122), (117, 127), (327, 128), (110, 133), (342, 134), (118, 139), (342, 140), (145, 145), (323, 146), (152, 151), (324, 152), (161, 157), (323, 158), (175, 163), (317, 164), (183, 169), (317, 170), (171, 175), (337, 176), (198, 181), (318, 182), (241, 187), (283, 188), (1348, 193), (272, 194) 仔细看发现,每两种颜色值相邻,可以分为一组(1和2, 7和8, 13和14 ...), 每组颜色的像素数累加后开平方可得一个整数,比如颜色1和2的像素数 sqrt(1532+232)=42, 颜色1,2,7和8的像素数 sqrt(1532+232+963+189)=54 颜色1,2,7,8,13和14的像素数 sqrt(1532+232+963+189+724+329)=63 再根据提示中的 light , remove its power 和 square 猜想: 0) 以所有像素为整体开始; 1) 以当前像素数开平方的值做为宽高建立新图片; 2) 将当前像素中颜色值最大的一组像素标为最暗其他则标为最亮(反过来也行),然后输出到新图片中; 3) 从当前像素中去掉当前颜色值最大的一组(因为最亮嘛),然后转到第1)步; 如此循环共建立33个新图片,查看一下输出是否有意义 源代码如下: amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / def level_33(): amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / img=Image.open(r amp;amp;amp;amp;#39;d:beer2.png amp;amp;amp;amp;#39;) amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / colors=img.getcolors() amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / cl=len(colors) amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / l=img.getdata() # 当前操作的像素集合 amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / ## starttime=clock() amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / amp;amp;amp;lt;/p amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / amp;amp;amp;lt;p amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / i=cl-1 # 65 amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / while i amp;amp;amp;amp;gt;0: amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / amp;gt; lt;br / gt; br / dim=sqrt(len(l)) # 确定宽高 amp;amp;amp;lt;br / amp;amp;amp;gt; amp;amp;lt;br / amp;amp;gt; amp;lt;br / am ...

阅读全文 »