星期五, 九月 28, 2007

Web测试自动化

最近一段时间在开发一个Web项目,发现Web测试自动化非常有必要,因为经常对代码有一些改动,但很难"充分"保证改动对系统没有坏的影响,我想除了全面的自动测试,应该没有更好的方法了。

针对一般的服务器端脚本的Web(比如PHP)测试相当简单,只需要支持少量的HTTP请求就可以了,所以有很多工具甚至只提供XML驱动的测试用例的编写方式(XML就意味着没有什么逻辑能力),比如 Imprimatur,或者是"记录"-"重放"机制,比如iMacros

当然也有很多工具是要求写脚本的,比如Webinject,sahi等,这些我没用过。

但如果Web包含了大量的Javascript-AJAX,则事情就变得麻烦起来,不过还好暂时我没有这个需求,以后再研究吧。

星期六, 九月 15, 2007

网页内存大户- Gmail

Ajax很酷,但是酷需要代价,使用firefox打开Gmail页面,在inbox和sent mail间点两下,就可以发现firefox的内存耗用会飚升将近30M(在我的PC上从44M到70M左右),这个内存消耗大致和我们著名的sina首页差不多。

我有兴趣顺便测试了另外几个大的网站,Amazon和MSN首页的内存耗用都很小,从44M上升到50M左右,而这两个网页的首页内容也是相当丰富的,能说明什么问题?

可惜firefox不会自动释放页面占用的内存,这使得一旦我打开了象Gmail和Sina这样的网页,我的firefox就噌的一下涨胖,挤占了系统的大量宝贵内存,真的不喜欢firefox的这个特性。 :(


星期四, 九月 13, 2007

php python sort

php的数组类似于python的字典和list的组合,但我觉得奇怪的是,当php数组做字典来用时,居然可以排序,而且可以按值或者按key来排序都可以,分别用sort和ksort,比如
a = array("one"=>1, "two"=>2, "three"=>3);
sort(a);
ksort(a);
这从python的角度来说很难理解,因为字典的key应该是使用hash来访问的,不支持排序的(即使key是int也不行),只能转换为list之后排序:
甚至有一篇专门的PEP解释这个: http://www.python.org/dev/peps/pep-0265/

而php的数组是怎么访问的呢,也许是链接+hash(下标访问时用hash,遍历时用链表),这样排序就相当于重排链表。

星期三, 九月 12, 2007

fcitx 内存处理?

使用htop很容易发现一个问题,当系统启动后,fcitx占用1M的内存,而当输入第一个汉字之后,fcitx的内存占用狂飙到17M,并维持这个峰值。

看了一下fcitx源码就很容易理解这个行为了,当用户第一次输入时,fcitx才开始加载码表,并且永不释放,我感到奇怪的是,为什么把码表全部放在内存里(因为现在的拼音输入法,码表还是挺大的,尤其是有大量词汇的时候)。

做了简单的实验,在加载完拼音单字码表后内存占用大约在4M左右,而加载完词组的码表后,就飙到了17M了。 我想如果能够优化一下的话,比如将词组通过数据库的形式放在磁盘文件中,那么就可以大幅降低这个内存的消耗了,毕竟输入法是个常驻内存的程序,17M的内存消耗还是太大了。

星期二, 九月 11, 2007

Python Patterns

因为写一个小程序,所以对这个感起兴趣了,

python的特点会影响设计模式在python中的使用:
× 动态类型 - 一定会使得很多pattern在实现上要简单一些
× 面向对象特征的简化 - 这可能会让一些pattern难以实现,比如封装的不完全实现使得python实现单件可能要复杂的多。

但感觉前者带来的优点应该大于后者带来的缺点,这只是一些初步的感想。
需要找一些书充充电了。。。

一个网页: http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html

Python Patterns

因为写一个小程序,所以对这个感起兴趣了,

python的特点会影响设计模式在python中的使用:
× 动态类型 - 一定会使得很多pattern在实现上要简单一些
× 面向对象特征的简化 - 这可能会让一些pattern难以实现,比如封装的不完全实现使得python实现单件可能要复杂的多。

但感觉前者带来的优点应该大于后者带来的缺点,这只是一些初步的感想。
需要找一些书充充电了。。。

一个网页: http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html

星期一, 九月 10, 2007

PHP得到Mysql的id字段

很多数据库表中都有id字段(autoincrement的主key),使用php往里插入记录时不需要填id,mysql会自动生成这个id,但这个id怎么传回给php呢?因为接下来的代码可能要用这个id(比如将这个id存到另一个表中)

答案很简单: php提供了一个mysql_insert_id()函数可以得到这个id。

在insert成功之后立刻用这个函数就可以了,但如果这个id字段在Mysql中定义为BIGINT,则不能这么用(这是手册里说的,没有试过),可以直接在Select语句中用SQL函数LAST_INSERT_ID()。

千万要避免的方法是: 在insert之后用 select max(id)去当做新插入的id,这种方法大部分情况下可行,但一旦有多人操作数据库,正好在insert之后select max之前又有别人插入一条记录进去,那么selct max就会死的很惨了。

星期日, 九月 09, 2007

Python Import 分析

在用python package的时候,很容易混淆的语法就是:
1) from path.package import *
2) from path.package.module import *
3) from path.package import module
4) from path.package.module import name
5) import path.package.module
6) import path.package
7) from path.package import subpackage
语法上这些都是可以的,其中6),7)没有什么大的意义(因为module没有引入), 2)4)不推荐使用(shallow copy的原因),1)受到文件系统的影响,比如早期的Windows版本在列文件时总是"自作主张"的将首字母大写,这样python就得不到所需要import的模块的"真正名字",因此只能依靠package文件夹的__init__.py中定义的__all__列表来加载对应的模块,这也比较麻烦,因为修改module名字之后需要同步更新这个__init__.py文件。

所以比较好的方法是 3和5,两者只是名字空间使用上稍有差别。

星期六, 九月 08, 2007

贪婪匹配与非贪婪匹配

这个在正则表达式中是很有用的,python的re模块的正则表达式中,
?,*,+ 缺省都是贪婪匹配,
在它们后面加一个?就可以变成非贪婪匹配,很方便啊, 也就是
??,*?,+?

例子送上:
>>> re.findall("<big>.+?</big>", "<big>1</big><big>2</big>3")
['<big>1</big>', '<big>2</big>']
>>> re.findall("<big>.+</big>", "<big>1</big><big>2</big>3")
['<big>1</big><big>2</big>']

 

星期五, 九月 07, 2007

数据库字段名称

一定要记住了,不要用"when","where"这样的名称做数据库字段名, 我已经第二次犯这个错误了,这次记在blog里,希望以后不会再忘。

这些名称可以成功用做字段名,但在select时如果使用这些字段名则和SQL语句的关键字冲突, 后果自然。。。
而且很多情况下,等我发现冲突时,很多其它代码中已经用到了这个名字了,于是又是改数据库,又是改代码,相当的麻烦。

星期四, 九月 06, 2007

python urllib & urllib2

很难找到详细的文档说明urllib和urllib2的区别,不过从帮助等的比较来看,urllib2功能要更强一些,支持proxy,proxy(认证也支持),http request等。我在Linux下的测试说明,使用urllib,不能在连接失败时抛出异常,而urllib2可以。

这里有urllib2的介绍:  http://www.voidspace.org.uk/python/articles/urllib2.shtml
但没有涉及urllib于urllib2的差异,

星期三, 九月 05, 2007

Python转码

简单的方法就是 str=str.decode("gb2312").encode("utf-8")'
decode是为了得到unicode字符串,encode回到utf-8编码。
如果编码选择错误或者字符内容编解码错误都会触发相应的异常。

最终encode得到的字符串如果和OS的编码(locale)不一致的话,print时就会出现乱码。

星期日, 九月 02, 2007

python 中执行外部命令并得到输出

在python中实现这个相当简单:
pipe = os.popen(command)
text = pipe.read()
pipe.close()

在Linux下,如果这个command是带重定向的,这里也可以正常使用,比如command是" echo sskdf > ttt ",那么执行后,ttt文件会生成, 上面代码中的text就是空字符串了。

而如果标准错误输出没有定向的话,也会从上面的pipe读进来,比如command是 " cp sdfjsfd skfdjdf > ttt ",  这里两个文件名都是不存在的,所以cp命令会在标准错误输出送出一些提示信息, 它不会被定向到ttt文件,所以也会被pipe截取到字符串中。

Windows下,我没有验证,我打赌有点问题, 呵呵:)