Wednesday, August 10, 2011

快速建立Pylons CI环境

因目前业务还跑在Pylons上,因此就拿Pylons来做这个例子吧。其他Python环境应该也是大同小异的。

CI系统环境:
OS: Ubuntu
CI 工具: Hudson 1.396
单元测试工具: nosetests

Hudson 本身的安装使用就不细写了,网上现在已经有很多了。直接下载war包,用java -jar运行即可。
启动之后,在管理界面中安装 Hudson Cobertura plugin、Python Plugin、Hudson Violations plugin、Subversion Plugin等插件即可。

一、建立虚拟环境
为了使Hudson同时支持多个python项目的持续集成,建议为每一个项目建立独立的虚拟环境,以便更清楚与项目相关联的包的情况,方便今后的部署。

下面几个步骤即可建立一个基本的虚拟环境。
1. 找到virtualenv包,取出其中的virtualenv.py
2. 运行python virtualenv.py --no-site-packages pylons-0.9.7 建立一个名字叫pylons-0.9.7的虚拟环境。这里 --no-site-packages参数是为了排除linux系统自带的python包对项目的影响,加了这个参数即可建立比较干净的Python虚拟环境。
3. 启动刚才建立的虚拟环境 source pylons-0.9.7/bin/activate
4. 运行easy_install nose 安装nosetests单元测试工具
5. 运行easy_install fudge 安装fudge Mock工具
6. 运行easy_install nosexcover 安装覆盖率生成工具,这个工具可以生成hudson中需要的xml格式的报表。仅仅安装coverage包不能生成类似报表。

二、建立项目运行环境
现在一个基本的环境已经基本建立完成了。下面在安装一些该项目特定的包
1. 安装mysql python包、sqlalchemy包
sudo apt-get install libmysqlclient-dev (MySQL-python编译安装需要mysql client开发环境)
easy_install MySQL-python
easy_install "sqlalchemy==0.5.8"
2. 安装pylons
easy_install -Z "pylons==0.9.7"
在pylons-0.9.7/lib/python26/site-packages/WebOb-1.1beta1-py2.6.egg/webob/__init__.py中加入一行from webob.multidict import UnicodeMultiDict
(pylons下载了最新的webob,里面有些改动,pylons 0.9.7不支持,需要改下)

3. 再按装写杂七杂八的项目用到的包
easy_install pycrypto
easy_install recaptcha_client
easy_install python-memcached

好了,一个pylons虚拟环境基本完成了,可以先直接下载项目代码运行nosetests看看有没有什么问题,如果运行都正常,即可进行以下步骤

三、建立Hudsong项目
1. 在Hudson中新建一个任务,选择“构建一个自由风格的软件项目“
2. 输入代码地址(SVN/CVS...)
3. 按照crontab规则建立build规律
4. 选择shell脚本作为build命令,在里面输入如下内容:
. /home/mm/pylons-0.9.7/bin/activate
cd ${WORKSPACE}
nosetests --cover-package=包名 --cover-tests --with-xcoverage --with-xunit --verbose

注:这里报名替换成需要测试覆盖率的包名
5. 设置输出报表
Publish JUnit test result report
xml文件直接输入 nosetests.xml
Publish Cobertura Coverage Report
xml文件直接输入 coverage.xml

Sunday, August 7, 2011

code review 之我见

近期code review的讨论貌似很多,也来凑下热闹,说说自己的一些认识和想法。

一、常见误区

1. 在我经历过的很多团队中,貌似不少人员都认为code review是一种上级的管理手段。毕竟翻译成中文叫“代码评审

”,这又评又审的,很多人就已经开始心里打鼓了,这嘴上不说,心底里早就开始抵触上了。这种情绪下还能指望即时

的review么?

2. code review不能算是考核工具,很多管理者都会有review出一个问题,扣多少多少类似的想法,把review简简单单

的当成了抓虫子,从而造成了更多的开发人员的抵触。一review就变味成了给开发挑刺,然后升级成双方攻防战,搞得

面红耳赤,你死我活的,最后一拍两散。

3. code review也不是个人技术挑战赛,这在很多年轻气盛的开发人员中很常见,“凭什么给他看”,“他又看不懂”

是这类人经常会说的话。其实从来没有人规定过review一定要找更厉害的人,一定要找出问题来的。

4. review是每一个团队成员的事,而不仅仅是经理或者架构师的事。这在传统的开发团队里面很常见,代码开发完了

一丢,就没自己啥事了。在敏捷开发中,review应该是每一个成员自发的行为。


二、一点想法

1. 整个团队必须保持一个开放的心态,能够虚心听取他人意见,战斗的团队是指对外战斗,不是内斗。

2. 必须建立一个前提认识:代码共享,团队中每个人都能随时浏览他人最新代码。代码不是私人物品,不能敝帚自珍。

3. 明确一个观点:任何review都不是挑错,是一种相互探讨,追求更高质量,更优代码的过程,是团队共同进步的一种手段。

4. review中每个人都是平等的,没有谁服从谁的概念。每个参与review的人要有包容的心态,不是只有你的解决办法是最优的

5. 得有一个公认的代码标准,最好能持续维护一个知识库,将一些优秀的代码、历史的review经验积累起来。

6. review要经常化,每次review的量要小,最好完成一个功能就review它。一次review一整个项目任谁都会烦。

7. 提交代码的时候要写清楚,也要有点必要的注释或文档,不要让别人去猜,浪费大家时间。

Tuesday, August 2, 2011

Pyramid 学习笔记:创建Pyramid项目(下)

除了在项目根目录生成了一系列项目配置性文件之外,Pyramid还生成了一个简单的项目框架结构以方便开发人员编写代码。这些文件统一放在了myproject这个目录下面。

一、__init__.py文件
该文件主要定义了项目入口方法。主要代码如下:

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(root_factory=Root, settings=settings)
    config.add_view(’myproject.views.my_view’,
                     context=’myproject.resources.Root’,
                     renderer=’myproject:templates/mytemplate.pt’)
    config.add_static_view(’static’, ’myproject:static’)
    return config.make_wsgi_app()

这个main函数是Pyramid自动生成的本项目的入口,这里global_config, settings两个参数分别对应于development.ini(或production.ini)中的DEFAULT段和app:myproject段的内容。本函数主要功能就是完成了使用traversal机制进行URL映射的配置过程。traversal机制是受zope启发而来的一种URL映射机制,可以构建比较复杂的URL结构。如果URL结构比较简单的化,可以使用ROUTE机制,比较直观一点。
该函数最后返回一个WSGI应用以启动本应用。

二、view.py文件
Pyramid应用中的大部分实现都是在view中实现的,这个可以看作pylons中的controller。在我们生成的项目中,view.py只有一个简单的函数:
def my_view(request):
return {'project':'myproject'}
在前面提到的__init__.py中,我们通过add_view函数注册到了系统中。因此运行这个应用之后,直接浏览 / 看到的就是调用了这个函数而返回的结果(经模板渲染之后)。

三、resources.py文件
这个文件就是用于traversal机制来映射URL时提供站点结构等资源的文件。我们通常用一个Root类来表示这些资源的根。每次接到WEB请求的时候,Pyramid Router通过这个类来找到本项目资源树的根。

四、静态文件目录
主要包含CSS、图片等静态文件

五、模板目录
存放项目开发用的模板文件。这也是在__init__.py中被add_view注册到系统中,并且与一个view关联。

六、test.py
这就是单元测试文件。

Pyramid生成的这个项目框架其实是很简单的一个结构,基本上是无法满足我们项目开发的需要的,一般我们都会修修改改再在项目中使用,也可以修改后生成一套scaffold以便今后重复利用。
一般情况下,我们都会做如下修改:
* view包,以及多层的包结构,如果应用比较复杂的话。
* 单元测试包结构
* URL映射如果复杂的化最好也能独立出来
* lib包,如果需要的话
* model包,如果有数据库支持的话

总体感觉,Pyramid生成的代码在项目代码结构的指导意义上不如pylons,也没Pylons那么严谨周全,要动的东西很多,需要抽个时间好好整理一个能用的东西出来。

本文提到的示例材料均源于Pyramid官方网站