<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>进化的测试 &#187; python</title>
	<atom:link href="http://magustest.com/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://magustest.com/blog</link>
	<description>软件测试，自动化测试，白盒测试，Python</description>
	<lastBuildDate>Thu, 17 May 2012 14:19:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>SST (selenium-simple-test) 介绍</title>
		<link>http://magustest.com/blog/automationtesting/sst-selenium-simple-test/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sst-selenium-simple-test</link>
		<comments>http://magustest.com/blog/automationtesting/sst-selenium-simple-test/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 09:09:26 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sst]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=841</guid>
		<description><![CDATA[今天扫博客发现一个新的自动化测试框架，就是这个SST (selenium-simple-test) ，地址：http://testutils.org/sst/ 项目在这里：https://launchpad.net/selenium-simple-test SST是在selenium python binding的基础上，抽象出一些称之为actions的API，还有整合了一些工具，例如SST自带一个测试报告模块，测试结果可以以console, html和xml格式展示。并且提供了一个简单的以目录形式管理的测试用例的管理方式。 我试用了一下，他主要还是走selenium的路子，把所有操作都放在sst.actions里面，脚本写出来就是一条条的操作。如果是webdriver的思路的话，就是先有一个浏览器对象，然后针对这个浏览器对象进行操作。 from sst.actions import * &#160; go_to&#40;'http://www.ubuntu.com/'&#41; assert_title_contains&#40;'Ubuntu'&#41; &#160; # Search ubuntu on ubuntu website... keyword = 'ubuntu' write_textfield&#40;'edit-keys', keyword&#41; click_element&#40;'edit-submit'&#41; &#160; # Verify search result page assert_text&#40;'edit-keys', keyword&#41; assert_element&#40;id='search-results-container'&#41; 这个是作者的博客，大家可以去吐吐槽。http://coreygoldberg.blogspot.com/2012/01/officially-introducing-sst-python-web.html  对于这个框架的看法： 多一种选择总是好的，尤其对于使用selenium的python朋友 对比面向对象的调用方式，其实我本人挺喜欢这种selenium风格的脚本 项目才0.1.0，存在各种风险，用到production需谨慎 项目计划未知，这可能就是最后一个版本 ：P 大家都喜欢重复造轮子，有重复造轮子倾向的可以以这个轮子为基础继续造下去，哈哈 Related posts: WebDriver + TestNG 应用 实现数据驱动的CodedUI Test <a href='http://magustest.com/blog/automationtesting/sst-selenium-simple-test/' class='excerpt-more'>[...]</a>
Related posts:<ol>
<li><a href='http://magustest.com/blog/automationtesting/webdriver-testng/' rel='bookmark' title='WebDriver + TestNG 应用'>WebDriver + TestNG 应用</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
<li><a href='http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/' rel='bookmark' title='Selenium中被误用的XPath'>Selenium中被误用的XPath</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>今天扫博客发现一个新的自动化测试框架，就是这个SST (selenium-simple-test) ，地址：<a href="http://testutils.org/sst/" target="_blank">http://testutils.org/sst/</a> 项目在这里：<a href="https://launchpad.net/selenium-simple-test" target="_blank">https://launchpad.net/selenium-simple-test</a></p>
<p>SST是在selenium python binding的基础上，抽象出一些称之为actions的API，还有整合了一些工具，例如SST自带一个测试报告模块，测试结果可以以console, html和xml格式展示。并且提供了一个简单的以目录形式管理的测试用例的管理方式。</p>
<p>我试用了一下，他主要还是走selenium的路子，把所有操作都放在sst.actions里面，脚本写出来就是一条条的操作。如果是webdriver的思路的话，就是先有一个浏览器对象，然后针对这个浏览器对象进行操作。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> sst.<span style="color: black;">actions</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
go_to<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.ubuntu.com/'</span><span style="color: black;">&#41;</span>
assert_title_contains<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ubuntu'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search ubuntu on ubuntu website...</span>
<span style="color: #dc143c;">keyword</span> = <span style="color: #483d8b;">'ubuntu'</span>
write_textfield<span style="color: black;">&#40;</span><span style="color: #483d8b;">'edit-keys'</span>, <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span>
click_element<span style="color: black;">&#40;</span><span style="color: #483d8b;">'edit-submit'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Verify search result page</span>
assert_text<span style="color: black;">&#40;</span><span style="color: #483d8b;">'edit-keys'</span>, <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span>
assert_element<span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=<span style="color: #483d8b;">'search-results-container'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>这个是作者的博客，大家可以去吐吐槽。<a href="http://coreygoldberg.blogspot.com/2012/01/officially-introducing-sst-python-web.html" target="_blank">http://coreygoldberg.blogspot.com/2012/01/officially-introducing-sst-python-web.html</a><br />
<br />
对于这个框架的看法：</p>
<ul>
<li>多一种选择总是好的，尤其对于使用selenium的python朋友</li>
<li>对比面向对象的调用方式，其实我本人挺喜欢这种selenium风格的脚本</li>
<li>项目才0.1.0，存在各种风险，用到production需谨慎</li>
<li>项目计划未知，这可能就是最后一个版本 ：P</li>
<li>大家都喜欢重复造轮子，有重复造轮子倾向的可以以这个轮子为基础继续造下去，哈哈</li>
</ul>
<p>Related posts:<ol>
<li><a href='http://magustest.com/blog/automationtesting/webdriver-testng/' rel='bookmark' title='WebDriver + TestNG 应用'>WebDriver + TestNG 应用</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
<li><a href='http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/' rel='bookmark' title='Selenium中被误用的XPath'>Selenium中被误用的XPath</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/sst-selenium-simple-test/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python SQLite的使用经验</title>
		<link>http://magustest.com/blog/python/python-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=python-sqlite</link>
		<comments>http://magustest.com/blog/python/python-sqlite/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 10:18:29 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=822</guid>
		<description><![CDATA[SQLite是一款轻量级的数据库，很适合用着移动设备上，或者是客户端程序。SQLite的优点有：1. 不需要为数据库起一个单独的进程 2. 整个数据库可以随时拷贝走 3. 不需要任何配置。从Python 2.5开始，SQLite就在标准库了，所以用起来比较方便。下面是我使用过程中的一些使用经验。 连接到数据库？很简单。 import sqlite3 conn = sqlite3.connect&#40;'/tmp/sqlite_db'&#41; cur = conn.cursor&#40;&#41; 接下来干嘛呢？建一张表吧。这里需要注意的是，SQLite不支持在创建表的同时创建索引，所以要分两步走，先创建表然后再创建索引 create_table_stmt = ''' CREATE TABLE IF NOT EXISTS test_table ( id TEXT, duration INTEGER, event_date TEXT, parameter TEXT );''' create_index = 'CREATE INDEX IF NOT EXISTS idx_id ON test_table (id);' cur.execute&#40;create_table_stmt&#41; cur.execute&#40;create_index&#41; conn.commit&#40;&#41; 然后往里面插一点数据吧，SQLite只支持5种基本的数据类型 NULL. The value is <a href='http://magustest.com/blog/python/python-sqlite/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sqlite.org/" target="_blank">SQLite</a>是一款轻量级的数据库，很适合用着移动设备上，或者是客户端程序。SQLite的优点有：1. 不需要为数据库起一个单独的进程 2. 整个数据库可以随时拷贝走 3. 不需要任何配置。从Python 2.5开始，SQLite就在标准库了，所以用起来比较方便。下面是我使用过程中的一些使用经验。</p>
<h3>连接到数据库？很简单。</h3>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> sqlite3
conn = sqlite3.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/sqlite_db'</span><span style="color: black;">&#41;</span>
cur = conn.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<h3>接下来干嘛呢？建一张表吧。这里需要注意的是，SQLite不支持在创建表的同时创建索引，所以要分两步走，先创建表然后再创建索引</h3>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">create_table_stmt = <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
    CREATE TABLE IF NOT EXISTS test_table (
    id TEXT,
    duration INTEGER,
    event_date TEXT,
    parameter TEXT
);'</span><span style="color: #483d8b;">''</span>
create_index = <span style="color: #483d8b;">'CREATE INDEX IF NOT EXISTS idx_id ON test_table (id);'</span>
cur.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>create_table_stmt<span style="color: black;">&#41;</span>
cur.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>create_index<span style="color: black;">&#41;</span>
conn.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>然后往里面插一点数据吧，SQLite只支持5种基本的数据类型</p>
<blockquote><p>
<br />
<b>NULL</b>. The value is a NULL value.<br />
<b>INTEGER</b>. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.<br />
<b>REAL</b>. The value is a floating point value, stored as an 8-byte IEEE floating point number.<br />
<b>TEXT</b>. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).<br />
<b>BLOB</b>. The value is a blob of data, stored exactly as it was input.</p></blockquote>
<p>问题来了，SQLite的时间和日期类型在哪里？原来SQLite可以把时间日期保存在一下几种数据类型里面</p>
<blockquote><p>
<br />
<b>TEXT</b> as ISO8601 strings (“YYYY-MM-DD HH:MM:SS.SSS”).<br />
<b>REAL</b> as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.<br />
<b>INTEGER</b> as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.</p></blockquote>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">insert_stmt = <span style="color: #483d8b;">'insert into test_table values (?, ?, ?, ?)'</span>
record = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'test'</span>, <span style="color: #ff4500;">123</span>, <span style="color: #483d8b;">'2011-11-30 12:34:56'</span>, <span style="color: #483d8b;">'hello'</span><span style="color: black;">&#41;</span>
cur.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>insert_stmt, record<span style="color: black;">&#41;</span>
conn.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<h3>把日期保存为字符串以后，不能直接拿出来直接当日期用，在用之前要调用SQLite的date函数</h3>
<p>例如找前一天存进去的数据：</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> 
    id<span style="color: #66cc66;">,</span> 
    duration<span style="color: #66cc66;">,</span> 
    event_date<span style="color: #66cc66;">,</span> 
    parameter 
<span style="color: #993333; font-weight: bold;">FROM</span> test_table
<span style="color: #993333; font-weight: bold;">WHERE</span>
    <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span>event_date<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'now'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'-1 day'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'localtime'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> id<span style="color: #66cc66;">,</span> event_date</pre></div></div>

<h3>SQLite没有show tables，怎么查询数据库里面有什么表？</h3>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> name <span style="color: #993333; font-weight: bold;">FROM</span> sqlite_master <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;table&quot;</span></pre></div></div>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/python/python-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebDriver配置Firefox代理服务器</title>
		<link>http://magustest.com/blog/webdriver/proxy-config-of-firefox-driver/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=proxy-config-of-firefox-driver</link>
		<comments>http://magustest.com/blog/webdriver/proxy-config-of-firefox-driver/#comments</comments>
		<pubDate>Fri, 23 Sep 2011 06:49:21 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Selenium]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=808</guid>
		<description><![CDATA[这玩意儿网上很多，但是坑更多，现在记录一个肯定能用的。 我的环境是Python 2.6 + Selenium 2.6 from selenium import webdriver profile = webdriver.FirefoxProfile&#40;&#41; profile.set_preference&#40;'network.proxy.type', 1&#41; profile.set_preference&#40;'network.proxy.http', 'proxy_url'&#41; profile.set_preference&#40;'network.proxy.http_port', 3128&#41; profile.set_preference&#40;'network.proxy.ssl', 'proxy_url'&#41; profile.set_preference&#40;'network.proxy.ssl_port', 3128&#41; profile.update_preferences&#40;&#41; driver = webdriver.Firefox&#40;profile&#41; 这些坑分别是： 有些地方只告诉你配置network.proxy.http和network.proxy.http_port。但是如果不设置network.proxy.type，一切都是浮云。这个配置是个整数，默认是0，就是直接连接；1就是手工配置代理。 profile.set_preference(&#8216;network.proxy.type&#8217;, 1) 那个端口号3128是整数 profile.set_preference(&#8216;network.proxy.http&#8217;, &#8216;proxy_url&#8217;) profile.set_preference(&#8216;network.proxy.http_port&#8217;, 3128) 如果有些资源是https的，是需要另外配置network.proxy.ssl和network.proxy.ssl_port的。例如facebook的图片。。。 set完以后，是需要update_preferences的。。。 profile.update_preferences() 最后贴一个完整的Firefox配置参数表：http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries 如果发现自己的配置好像没有生效，那么在webdriver启动的Firefox里面输入about:config。然后对着上面那个配置参数表来看。总会发现掉哪个坑的。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>这玩意儿网上很多，但是坑更多，现在记录一个肯定能用的。</p>
<p>我的环境是Python 2.6 + Selenium 2.6</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> selenium <span style="color: #ff7700;font-weight:bold;">import</span> webdriver
<span style="color: #dc143c;">profile</span> = webdriver.<span style="color: black;">FirefoxProfile</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">set_preference</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'network.proxy.type'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">set_preference</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'network.proxy.http'</span>, <span style="color: #483d8b;">'proxy_url'</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">set_preference</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'network.proxy.http_port'</span>, <span style="color: #ff4500;">3128</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">set_preference</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'network.proxy.ssl'</span>, <span style="color: #483d8b;">'proxy_url'</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">set_preference</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'network.proxy.ssl_port'</span>, <span style="color: #ff4500;">3128</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">profile</span>.<span style="color: black;">update_preferences</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
driver = webdriver.<span style="color: black;">Firefox</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">profile</span><span style="color: black;">&#41;</span></pre></div></div>

<p>这些坑分别是：</p>
<p>有些地方只告诉你配置network.proxy.http和network.proxy.http_port。但是如果不设置network.proxy.type，一切都是浮云。这个配置是个整数，默认是0，就是直接连接；1就是手工配置代理。<br />
profile.set_preference(&#8216;network.proxy.type&#8217;, 1) </p>
<p>那个端口号3128是整数<br />
profile.set_preference(&#8216;network.proxy.http&#8217;, &#8216;proxy_url&#8217;)<br />
profile.set_preference(&#8216;network.proxy.http_port&#8217;, 3128)</p>
<p>如果有些资源是https的，是需要另外配置network.proxy.ssl和network.proxy.ssl_port的。例如facebook的图片。。。</p>
<p>set完以后，是需要update_preferences的。。。<br />
profile.update_preferences()</p>
<p>最后贴一个完整的Firefox配置参数表：http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries</p>
<p>如果发现自己的配置好像没有生效，那么在webdriver启动的Firefox里面输入about:config。然后对着上面那个配置参数表来看。总会发现掉哪个坑的。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/webdriver/proxy-config-of-firefox-driver/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>在web.py中处理表单中的多选下拉框</title>
		<link>http://magustest.com/blog/python/webpy-multiple-select-option/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=webpy-multiple-select-option</link>
		<comments>http://magustest.com/blog/python/webpy-multiple-select-option/#comments</comments>
		<pubDate>Sat, 25 Dec 2010 10:46:15 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[web.py]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=736</guid>
		<description><![CDATA[web.py是一个轻量级的web framework，源代码只有7000多行（我自己用wc -l计算，肯定偏多了），用它来做个简单的站点很方便，上手容易。我在公司就用web.py做了我们自己的自动化测试管理工具，主要是管理自动化用例，展示测试结果。最近遇到一个问题，我想做一个多选下拉框，但是等我做完以后发现结果跟我预想的不太一样。 我用的是web.py的web.form.Dropdown类来生成一个多选下拉框。只需在初始化dropdown的时候传一个multiple=”参数就OK了 form.Dropdown(&#8216;adserver_id&#8217;, description=&#8217;Adserver: &#8216;, args=ADSERVERS, multiple=”) 这样生成的html就是 &#60;select name=&#34;adserver_id&#34; id=&#34;adserver_id&#34; multiple=&#34;&#34;&#62; &#60;option value=&#34;1&#34;&#62;Coretest2 - 1&#60;/option&#62; &#60;option value=&#34;2&#34;&#62;Coretest3 - 1&#60;/option&#62; &#60;option value=&#34;3&#34;&#62;Coretest4 - 1&#60;/option&#62; &#60;option value=&#34;4&#34;&#62;Coretest2 - 2&#60;/option&#62; &#60;option value=&#34;5&#34;&#62;Coretest3 - 2&#60;/option&#62; &#60;option value=&#34;6&#34;&#62;Coretest4 - 2&#60;/option&#62; &#60;/select&#62; 不过当我选中多个选项提交表单的时候，我在服务端得到的结果却是最后一个选中的选项，例如我选了Coretest2 &#8211; 1和Coretest3 &#8211; 1，那么我在服务端拿到的数据就只有Coretest3 &#8211; 1。用Firebug抓了一下请求看，原来POST的数据是长这个样子的： adserver_id: 1 adserver_id: 2 在web.py中，一般是通过web.input()来获取表单提交的数据。而web.input()会把所有提交的数据给storify方法处理一下（可以更容易的访问dict的数据，例如原来是mydict['name']，可以写成mydict.name），而这个方法默认会把adserver_id处理成唯一的key，所以无论输入是多少个adserver_id，最终拿到的只有1个。解决方法很简单，用这个方法来获取post的数据web.input(adserver_id=[])，这样提交adserver_id的多个数据就会被保存到一个列表里面了。 但是这时候会遇到另一个问题，就是如果想要更改这个case的时候，就没有办法在web.py里面用 value=xxx 来指定哪些options是应该被选中的。value=xxx只能指定一个option，怎么办？我是用了JavaScript来解决。思路很简单，就是页面Load完以后，JavaScript获取一下哪些options应该被选中，然后就选上那些项，OK No related <a href='http://magustest.com/blog/python/webpy-multiple-select-option/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p><a href="http://webpy.org/" target="_blank">web.py</a>是一个轻量级的web framework，源代码只有7000多行（我自己用wc -l计算，肯定偏多了），用它来做个简单的站点很方便，上手容易。我在公司就用web.py做了我们自己的自动化测试管理工具，主要是管理自动化用例，展示测试结果。最近遇到一个问题，我想做一个多选下拉框，但是等我做完以后发现结果跟我预想的不太一样。</p>
<p>我用的是web.py的<a href="http://webpy.org/docs/0.3/api#web.form" target="_blank">web.form.Dropdown</a>类来生成一个多选下拉框。只需在初始化dropdown的时候传一个multiple=”参数就OK了</p>
<p>form.Dropdown(&#8216;adserver_id&#8217;, description=&#8217;Adserver: &#8216;, args=ADSERVERS, multiple=”)</p>
<p>这样生成的html就是</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;select</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;adserver_id&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;adserver_id&quot;</span> <span style="color: #000066;">multiple</span>=<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest2 - 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest3 - 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest4 - 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;4&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest2 - 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;5&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest3 - 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;option</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;6&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Coretest4 - 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/select<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>不过当我选中多个选项提交表单的时候，我在服务端得到的结果却是最后一个选中的选项，例如我选了Coretest2 &#8211; 1和Coretest3 &#8211; 1，那么我在服务端拿到的数据就只有Coretest3 &#8211; 1。用Firebug抓了一下请求看，原来POST的数据是长这个样子的：</p>
<blockquote><p>adserver_id: 1<br />
adserver_id: 2</p></blockquote>
<p>在web.py中，一般是通过web.input()来获取表单提交的数据。而web.input()会把所有提交的数据给storify方法处理一下（可以更容易的访问dict的数据，例如原来是mydict['name']，可以写成mydict.name），而这个方法默认会把adserver_id处理成唯一的key，所以无论输入是多少个adserver_id，最终拿到的只有1个。解决方法很简单，用这个方法来获取post的数据web.input(adserver_id=[])，这样提交adserver_id的多个数据就会被保存到一个列表里面了。</p>
<p>但是这时候会遇到另一个问题，就是如果想要更改这个case的时候，就没有办法在web.py里面用 value=xxx 来指定哪些options是应该被选中的。value=xxx只能指定一个option，怎么办？我是用了JavaScript来解决。思路很简单，就是页面Load完以后，JavaScript获取一下哪些options应该被选中，然后就选上那些项，OK</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/python/webpy-multiple-select-option/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python代码覆盖工具coverage.py介绍</title>
		<link>http://magustest.com/blog/whiteboxtesting/python-coverage-py/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=python-coverage-py</link>
		<comments>http://magustest.com/blog/whiteboxtesting/python-coverage-py/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 09:07:34 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[代码覆盖]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=710</guid>
		<description><![CDATA[最近是跟代码覆盖干上了，今天下午测试一个功能的时候，路过另一段代码，发现一个问题，由此想到既然C++都要搞代码覆盖，为什么不搞搞python的呢？很容易就找到了coverage.py ，这个工具比较简单，我用easy_install安装的，非常顺利。由于python不需要编译链接，所以这个工具使用非常简单。coverage run [options] your_cmd [cmd options]。 假如原来的运行的命令是： fact_compare.py -d result 需要收集代码覆盖信息的话只需要这样运行 coverage run &#8211;branch fact_compare.py -d result 运行完了以后会在当前目录下生成一个.coverage文件，保存了代码覆盖信息，可以用简单的coverage report看来简单的结果，当然，有更好的html结果显示 coverage html -d your_result_folder 最左边是绿，也就是没有颜色的代码的就是完全覆盖（其实只是语句覆盖和分支覆盖），黄色的是部分分支覆盖，红色的语句覆盖都不是。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>最近是跟代码覆盖干上了，今天下午测试一个功能的时候，路过另一段代码，发现一个问题，由此想到既然C++都要搞代码覆盖，为什么不搞搞python的呢？很容易就找到了<a href="http://nedbatchelder.com/code/coverage/" target="_blank">coverage.py</a> ，这个工具比较简单，我用easy_install安装的，非常顺利。由于python不需要编译链接，所以这个工具使用非常简单。coverage run [options] your_cmd [cmd options]。</p>
<p>假如原来的运行的命令是：</p>
<blockquote><p>fact_compare.py -d result</p></blockquote>
<p>需要收集代码覆盖信息的话只需要这样运行</p>
<blockquote><p>coverage run &#8211;branch fact_compare.py -d result</p></blockquote>
<p>运行完了以后会在当前目录下生成一个.coverage文件，保存了代码覆盖信息，可以用简单的coverage report看来简单的结果，当然，有更好的html结果显示</p>
<blockquote><p>coverage html -d your_result_folder</p></blockquote>
<p><a href="http://magustest.com/blog/wp-content/uploads/2010/09/截图01.png"><img class="alignnone size-full wp-image-713" title="截图01" src="http://magustest.com/blog/wp-content/uploads/2010/09/截图01.png" alt="" width="467" height="352" /></a></p>
<p>最左边是绿，也就是没有颜色的代码的就是完全覆盖（其实只是语句覆盖和分支覆盖），黄色的是部分分支覆盖，红色的语句覆盖都不是。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/python-coverage-py/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用Python对体积较大的CSV文件进行比较的经验</title>
		<link>http://magustest.com/blog/python/compare-big-csv-in-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=compare-big-csv-in-python</link>
		<comments>http://magustest.com/blog/python/compare-big-csv-in-python/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 14:31:22 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=664</guid>
		<description><![CDATA[最近的工作总是跟数据打交道，需要经常比较一些CSV文件，这些CSV文件其实都需要被LOAD到数据库里面，所以也就是一堆堆的数据文件需要比较。暂时没有发现有比较好用的现成的CSV比较工具，自己动手用Python做了一个凑合能用的。思想比较简单，就是把CSV文件的内容读取出来，保存为一个list，然后把2个CSV文件所生成的list进行对比。有个特殊的需求，就是对于CSV文件中一些肯定不一样的列，例如process date这样的字段，是需要跳过的。由于本地生成的CSV文件比较小，刚开始没有注意到如果文件太大的话会占用很多的内存。最开始的版本是： def readcsv2list&#40;filename, rows&#41;: fileobj = open&#40;filename, 'rb'&#41; csvreader = csv.reader&#40;fileobj&#41; retlist = &#91;&#93; for row in csvreader: clist = &#91;&#93; selected_rows = &#91;ic for ic in range&#40;len&#40;row&#41;&#41; if ic not in rows&#93; for c in selected_rows: clist.append&#40;row&#91;c&#93;&#41; retlist.append&#40;clist&#41; &#160; fileobj.close&#40;&#41; return retlist 后来用这个脚本比较生产环境数据的时候就遇到问题了，其中最大的一个数据文件大概是1.5GB，这只是文件大小，把文件转成list以后所占用的内存会翻几倍（这个很容易理解，整数1在文件里面站1个字节，放到list里面就要4个字节了）。一下子把机器的内存用光了。随后找了一下文档，csv.reader是没有一个方法可以指定一次读取若干行数据的。后来就利用file object有一个readline()方法，通过一个参数来控制一次读取多少行的记录，从而达到控制内存使用量的目的。需要的注意的点有：1. 在读完若干行数据以后，需要获取一下当前这个file object的位置，Python提供了.tell()方法来获取这个值；2. 读取文件的时候需要知道上一会读到什么地方了，并且从那里继续往下读，用到了.seek()方法；3. readline()方法在读到文件末尾的时候只会返回一个空字符，所以需要对这个空字符做一点处理。 def readcsv2list&#40;filename, rows, last_position, max_line&#41;: <a href='http://magustest.com/blog/python/compare-big-csv-in-python/' class='excerpt-more'>[...]</a>
Related posts:<ol>
<li><a href='http://magustest.com/blog/python/python-sqlite/' rel='bookmark' title='Python SQLite的使用经验'>Python SQLite的使用经验</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>最近的工作总是跟数据打交道，需要经常比较一些CSV文件，这些CSV文件其实都需要被LOAD到数据库里面，所以也就是一堆堆的数据文件需要比较。暂时没有发现有比较好用的现成的CSV比较工具，自己动手用Python做了一个凑合能用的。思想比较简单，就是把CSV文件的内容读取出来，保存为一个list，然后把2个CSV文件所生成的list进行对比。有个特殊的需求，就是对于CSV文件中一些肯定不一样的列，例如process date这样的字段，是需要跳过的。由于本地生成的CSV文件比较小，刚开始没有注意到如果文件太大的话会占用很多的内存。最开始的版本是：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> readcsv2list<span style="color: black;">&#40;</span>filename, rows<span style="color: black;">&#41;</span>:
    fileobj = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span>
    csvreader = <span style="color: #dc143c;">csv</span>.<span style="color: black;">reader</span><span style="color: black;">&#40;</span>fileobj<span style="color: black;">&#41;</span>
    retlist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> csvreader:
        clist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        selected_rows = <span style="color: black;">&#91;</span>ic <span style="color: #ff7700;font-weight:bold;">for</span> ic <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> ic <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> rows<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> selected_rows:
            clist.<span style="color: black;">append</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#91;</span>c<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        retlist.<span style="color: black;">append</span><span style="color: black;">&#40;</span>clist<span style="color: black;">&#41;</span>
&nbsp;
    fileobj.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> retlist</pre></div></div>

<p>后来用这个脚本比较生产环境数据的时候就遇到问题了，其中最大的一个数据文件大概是1.5GB，这只是文件大小，把文件转成list以后所占用的内存会翻几倍（这个很容易理解，整数1在文件里面站1个字节，放到list里面就要4个字节了）。一下子把机器的内存用光了。随后找了一下文档，csv.reader是没有一个方法可以指定一次读取若干行数据的。后来就利用file object有一个readline()方法，通过一个参数来控制一次读取多少行的记录，从而达到控制内存使用量的目的。需要的注意的点有：1. 在读完若干行数据以后，需要获取一下当前这个file object的位置，Python提供了.tell()方法来获取这个值；2. 读取文件的时候需要知道上一会读到什么地方了，并且从那里继续往下读，用到了.seek()方法；3. readline()方法在读到文件末尾的时候只会返回一个空字符，所以需要对这个空字符做一点处理。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> readcsv2list<span style="color: black;">&#40;</span>filename, rows, last_position, max_line<span style="color: black;">&#41;</span>:
    fileobj = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span>
    fileobj.<span style="color: black;">seek</span><span style="color: black;">&#40;</span>last_position<span style="color: black;">&#41;</span>
    datalines = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>max_line<span style="color: black;">&#41;</span>:
        line_itme = fileobj.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>line_itme<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
            datalines.<span style="color: black;">append</span><span style="color: black;">&#40;</span>line_itme<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
    csvreader = <span style="color: #dc143c;">csv</span>.<span style="color: black;">reader</span><span style="color: black;">&#40;</span>datalines<span style="color: black;">&#41;</span>
    retlist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> csvreader:
        clist = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        selected_rows = <span style="color: black;">&#91;</span>ic <span style="color: #ff7700;font-weight:bold;">for</span> ic <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> ic <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> rows<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> selected_rows:
            clist.<span style="color: black;">append</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#91;</span>c<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        retlist.<span style="color: black;">append</span><span style="color: black;">&#40;</span>clist<span style="color: black;">&#41;</span>
&nbsp;
    current_position = fileobj.<span style="color: black;">tell</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    fileobj.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> retlist, current_position</pre></div></div>

<p>Python，尤其是低版本（例如我们用的2.4.3），对于在程序里面显式地del一些变量（通常是个大list之类），是不会立刻释放内存的，所以对于处理数据量比较大的case的时候就需要特别注意内存的使用。参考文章：<br />
<a href="http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm" target=_blank> Python Memory Management</a><br />
<a href="http://evanjones.ca/python-memory.html" target=_blank> Why doesn&#8217;t Python release the memory when I delete a large object?</a></p>
<p>Related posts:<ol>
<li><a href='http://magustest.com/blog/python/python-sqlite/' rel='bookmark' title='Python SQLite的使用经验'>Python SQLite的使用经验</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/python/compare-big-csv-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DSL与自动化测试 – 用Python实现简单的DSL</title>
		<link>http://magustest.com/blog/python/dsl-automation-testing-using-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dsl-automation-testing-using-python</link>
		<comments>http://magustest.com/blog/python/dsl-automation-testing-using-python/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 06:15:32 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[DSL]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=655</guid>
		<description><![CDATA[自动化测试，一个在测试领域中被广为熟知，也是被谈论最多的概念之一。DSL (Domain Specific Language)，一种高度抽象，用于某个特定领域下编程语言。软件测试在大多数情况下都是对某个特定行业的软件系统进行测试，所以这两者应该可以很好的结合起来，事实上也是这样的，QTP里面的keyword view，其实就是DSL的一个实现。DSL一般可以分为两个大的类型，分别是External DSL 和 Internal DSL （引用自Martin Fowler）。External DSL 一般来说是跟其实现语言不一样的 DSL，常见的External DSL 有：SQL和XML配置文件；而Internal DSL 一般来说就是该DSL使用某个现成的编程语言（就是所谓的host language)，然后对host language进行一些改造而成。 我们在测试中会遇到很多问题，其中一些问题，几乎是所有公司所有团队都会遇到的，例如测试覆盖率不够，测试的时间不够等等。面对这些问题，自动化测试自然而然地成为解决这些问题的首选方法。但是自动化测试真的就是银弹麽？不见得！以前曾经在ASP.NET QA 的博客中给他们留言，请教过关于自动化测试的事情，我记得其中有一个回复是说，在某个release中过度地使用自动化测试，一切东西都想实现自动化测试，而忽略了产品本身的功能、特性的关注，结果就是超高的自动化测试覆盖率，但是很差的产品质量。大家都去实现自动化测试了，谁来做功能点的覆盖呢？某些领域的专家（SME），他们可能对测试技术是一无所知的，要把这些领域专家和测试实施结合起来，DSL就是一个比较好的桥梁。 我在工作中遇到的问题是，我需要测试一个类似UV（独立用户访问数）统计的系统，统计UV的方法其实就是根据_uid cookie的值来判断这个用户在某段时间内访问过我们的系统多少次，访问了哪些站点，进行了什么样的行为。其中有2个地方比较麻烦，第一就是在测试过程中要不断地拷贝cookie，这样拷来拷去两三次以后很容易就混乱，出错；第二就是需要记录访问哪些站点，这些站点都只是ID，也是需要不断地修改请求，测试时间长了也是很容易出错。所以我就打算在原来的测试工具基础上，实现一个简单的Internal DSL。先看成品： @tc def uniq_inventory_case01&#40;&#41;: test= testTool&#40;&#41; test.user&#40;'a'&#41;.view&#40;'asset55100002'&#41;.anetwork&#40;'55100'&#41;.onsite&#40;'site55100503'&#41;.snetwork&#40;'55100'&#41;.dnetwork&#40;'55100'&#41;.times&#40;1&#41;.go&#40;&#41; test.user&#40;'b'&#41;.view&#40;'asset55100002'&#41;.anetwork&#40;'55100'&#41;.onsite&#40;'site55100503'&#41;.snetwork&#40;'55100'&#41;.dnetwork&#40;'55100'&#41;.times&#40;2&#41;.go&#40;&#41; test.user&#40;'b'&#41;.view&#40;'asset55100002'&#41;.anetwork&#40;'55100'&#41;.onsite&#40;'site55100504_noad'&#41;.snetwork&#40;'55100'&#41;.dnetwork&#40;'55100'&#41;.times&#40;4&#41;.go&#40;&#41; 实例化一个testTool对象，然后就是指定哪个用户：user(&#8216;a&#8217;)或者user(&#8216;b&#8217;)，看的视频的ID：view(&#8216;asset55100002&#8242;)，这个视频属于哪个CRO呢？anetwork(&#8217;55100&#8242;)；放在哪个网站呢？onsite(&#8216;site55100503&#8242;)；网站是谁的呢？snetwork(&#8217;55100&#8242;)；谁是分发者呢？dnetwork(&#8217;55100&#8242;)；看了多少次呢？times(4)；最后一个有点儿丑陋的go()。 像这样子一句话里面N个方法连着用，就叫Method Chaining，Method Chaining通常可以让代码变得更加人性化，读起来更加容易。但是使用Method Chaining通常会遇到一个问题，就是很难判断就是到了哪个方法才是终结呢？是不是有些方法的调用是可选的，有些是必选的呢？其中一个解决方法就是我用到的，放一个.go()方法在最后，作为终结方法。要实现Method Chaining，其实只需要顶一个类，对于需要做连接的方法，最后都返回这个类的实例。例如： def view&#40;self, assetid&#41;: if assetid: self.asset_id = assetid return self &#160; def anetwork&#40;self, networkid&#41;: if <a href='http://magustest.com/blog/python/dsl-automation-testing-using-python/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>自动化测试，一个在测试领域中被广为熟知，也是被谈论最多的概念之一。DSL (Domain Specific Language)，一种高度抽象，用于某个特定领域下编程语言。软件测试在大多数情况下都是对某个特定行业的软件系统进行测试，所以这两者应该可以很好的结合起来，事实上也是这样的，QTP里面的keyword view，其实就是DSL的一个实现。DSL一般可以分为两个大的类型，分别是External DSL 和 Internal DSL （引用自Martin Fowler）。External DSL 一般来说是跟其实现语言不一样的 DSL，常见的External DSL 有：SQL和XML配置文件；而Internal DSL 一般来说就是该DSL使用某个现成的编程语言（就是所谓的host language)，然后对host language进行一些改造而成。</p>
<p>我们在测试中会遇到很多问题，其中一些问题，几乎是所有公司所有团队都会遇到的，例如测试覆盖率不够，测试的时间不够等等。面对这些问题，自动化测试自然而然地成为解决这些问题的首选方法。但是自动化测试真的就是银弹麽？不见得！以前曾经在ASP.NET QA 的博客中给他们留言，请教过关于自动化测试的事情，我记得其中有一个回复是说，在某个release中过度地使用自动化测试，一切东西都想实现自动化测试，而忽略了产品本身的功能、特性的关注，结果就是超高的自动化测试覆盖率，但是很差的产品质量。大家都去实现自动化测试了，谁来做功能点的覆盖呢？某些领域的专家（SME），他们可能对测试技术是一无所知的，要把这些领域专家和测试实施结合起来，DSL就是一个比较好的桥梁。</p>
<p>我在工作中遇到的问题是，我需要测试一个类似UV（独立用户访问数）统计的系统，统计UV的方法其实就是根据_uid cookie的值来判断这个用户在某段时间内访问过我们的系统多少次，访问了哪些站点，进行了什么样的行为。其中有2个地方比较麻烦，第一就是在测试过程中要不断地拷贝cookie，这样拷来拷去两三次以后很容易就混乱，出错；第二就是需要记录访问哪些站点，这些站点都只是ID，也是需要不断地修改请求，测试时间长了也是很容易出错。所以我就打算在原来的测试工具基础上，实现一个简单的Internal DSL。先看成品：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@tc
<span style="color: #ff7700;font-weight:bold;">def</span> uniq_inventory_case01<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">test</span>= testTool<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">test</span>.<span style="color: #dc143c;">user</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>.<span style="color: black;">view</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'asset55100002'</span><span style="color: black;">&#41;</span>.<span style="color: black;">anetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">onsite</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'site55100503'</span><span style="color: black;">&#41;</span>.<span style="color: black;">snetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">dnetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">times</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">go</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">test</span>.<span style="color: #dc143c;">user</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span>.<span style="color: black;">view</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'asset55100002'</span><span style="color: black;">&#41;</span>.<span style="color: black;">anetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">onsite</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'site55100503'</span><span style="color: black;">&#41;</span>.<span style="color: black;">snetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">dnetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">times</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">go</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">test</span>.<span style="color: #dc143c;">user</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span>.<span style="color: black;">view</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'asset55100002'</span><span style="color: black;">&#41;</span>.<span style="color: black;">anetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">onsite</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'site55100504_noad'</span><span style="color: black;">&#41;</span>.<span style="color: black;">snetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">dnetwork</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'55100'</span><span style="color: black;">&#41;</span>.<span style="color: black;">times</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>.<span style="color: black;">go</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>实例化一个testTool对象，然后就是指定哪个用户：user(&#8216;a&#8217;)或者user(&#8216;b&#8217;)，看的视频的ID：view(&#8216;asset55100002&#8242;)，这个视频属于哪个CRO呢？anetwork(&#8217;55100&#8242;)；放在哪个网站呢？onsite(&#8216;site55100503&#8242;)；网站是谁的呢？snetwork(&#8217;55100&#8242;)；谁是分发者呢？dnetwork(&#8217;55100&#8242;)；看了多少次呢？times(4)；最后一个有点儿丑陋的go()。</p>
<p>像这样子一句话里面N个方法连着用，就叫Method Chaining，Method Chaining通常可以让代码变得更加人性化，读起来更加容易。但是使用Method Chaining通常会遇到一个问题，就是很难判断就是到了哪个方法才是终结呢？是不是有些方法的调用是可选的，有些是必选的呢？其中一个解决方法就是我用到的，放一个.go()方法在最后，作为终结方法。要实现Method Chaining，其实只需要顶一个类，对于需要做连接的方法，最后都返回这个类的实例。例如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> view<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, assetid<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> assetid:     <span style="color: #008000;">self</span>.<span style="color: black;">asset_id</span> = assetid
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> anetwork<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, networkid<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> networkid:   <span style="color: #008000;">self</span>.<span style="color: black;">a_network_id</span> = networkid
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> snetwork<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, networkid<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> networkid:   <span style="color: #008000;">self</span>.<span style="color: black;">s_network_id</span> = networkid
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> dnetwork<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, networkid<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> networkid:   <span style="color: #008000;">self</span>.<span style="color: black;">d_network_id</span> = networkid
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> onsite<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, sectionid<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> sectionid:   <span style="color: #008000;">self</span>.<span style="color: black;">site_section_id</span> = sectionid
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> times<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, times<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> times<span style="color: #66cc66;">&gt;</span><span style="color: #ff4500;">0</span>:       <span style="color: #008000;">self</span>.<span style="color: black;">request_times</span> = times
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span></pre></div></div>

<p>最后一个终结方法go()，就做真正的处理</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> go<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">asset_id</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">site_section_id</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">times</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">a_network_id</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">s_network_id</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">prepareRequest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">request_times</span><span style="color: black;">&#41;</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">sendRequest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">cleanup</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        info = <span style="color: #483d8b;">'Required information missing, abort running.'</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span>info<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> info</pre></div></div>

<p>如果是实现一个External DSL 的话，的确难度不小；但是Internal DSL其实并不是很高深，也不是很难实现，在它的帮助下，可以把工作完成的更好，对自己以后维护测试用例也带来了不少方便。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/python/dsl-automation-testing-using-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python多行注释技巧</title>
		<link>http://magustest.com/blog/uncategorized/python-comment-multiline/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=python-comment-multiline</link>
		<comments>http://magustest.com/blog/uncategorized/python-comment-multiline/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 09:47:13 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[未分类]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=642</guid>
		<description><![CDATA[Python语言本身是没有注释多行的支持的，如果需要注册多行，可以用一个取巧的方法，就是把需要注释的代码块用三个引号括起来，赋值为一个永远都不会使用的字符串变量，例如： 1 2 3 4 5 6 7 8 9 10 11 12 13 __devilcomment = ''' if bCmpLog == &#34;True&#34;: self.appendAdsLogToCmpLog(&#34;&#34;) &#160; if bCmpBinaryLog == &#34;True&#34;: self.appendBinaryAdsLogToCmpLog(res) &#160; if bCompareResp == &#34;True&#34;: self.appendResponseToCmpLog(response_strs) &#160; print &#34;move new and debug logs&#34; self.tools.move (src_db,dst_db) ''' Related posts: 用PDB库调试Python程序
Related posts:<ol>
<li><a href='http://magustest.com/blog/python/use-pdb-debug-python/' rel='bookmark' title='用PDB库调试Python程序'>用PDB库调试Python程序</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Python语言本身是没有注释多行的支持的，如果需要注册多行，可以用一个取巧的方法，就是把需要注释的代码块用三个引号括起来，赋值为一个永远都不会使用的字符串变量，例如：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">__devilcomment = <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
if bCmpLog == &quot;True&quot;:
        self.appendAdsLogToCmpLog(&quot;&quot;)
&nbsp;
if bCmpBinaryLog == &quot;True&quot;:
        self.appendBinaryAdsLogToCmpLog(res)
&nbsp;
if bCompareResp == &quot;True&quot;:
    self.appendResponseToCmpLog(response_strs)
&nbsp;
print &quot;move new and debug logs&quot;
self.tools.move (src_db,dst_db)
'</span><span style="color: #483d8b;">''</span></pre></td></tr></table></div>

<p>Related posts:<ol>
<li><a href='http://magustest.com/blog/python/use-pdb-debug-python/' rel='bookmark' title='用PDB库调试Python程序'>用PDB库调试Python程序</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/uncategorized/python-comment-multiline/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>用PDB库调试Python程序</title>
		<link>http://magustest.com/blog/python/use-pdb-debug-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=use-pdb-debug-python</link>
		<comments>http://magustest.com/blog/python/use-pdb-debug-python/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 13:17:49 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[计算机技术]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=640</guid>
		<description><![CDATA[如果使用过微软技术的朋友应该体会过微软的Visual Studio系列IDE给debug程序带来的方便，换了个工作就没有Visual Studio了，对于我这种从未在非GUI环境下调试过程序的人来说实在有点不爽，今天花了点时间看了一下Python自带的pdb库，发现用pdb来调试程序还是很方便的，当然了，什么远程调试，多线程之类，pdb是搞不定的。 用pdb调试有多种方式可选： 1. 命令行启动目标程序，加上-m参数，这样调用myscript.py的话断点就是程序的执行第一行之前 python -m pdb myscript.py 2. 在Python交互环境中启用调试 &#62;&#62;&#62; import pdb &#62;&#62;&#62; import mymodule &#62;&#62;&#62; pdb.run(&#8216;mymodule.test()&#8217;) 3. 比较常用的，就是在程序中间插入一段程序，相对于在一般IDE里面打上断点然后启动debug，不过这种方式是hardcode的 if __name__ == &#34;__main__&#34;: a = 1 import pdb pdb.set_trace&#40;&#41; b = 2 c = a + b print &#40;c&#41; 然后正常运行脚本，到了pdb.set_trace()那就会定下来，就可以看到调试的提示符(Pdb)了 常用的调试命令 h(elp)，会打印当前版本Pdb可用的命令，如果要查询某个命令，可以输入 h [command]，例如：“h l” &#8212; 查看list命令 l(ist)，可以列出当前将要运行的代码块 (Pdb) l 497 pdb.set_trace() <a href='http://magustest.com/blog/python/use-pdb-debug-python/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>如果使用过微软技术的朋友应该体会过微软的Visual Studio系列IDE给debug程序带来的方便，换了个工作就没有Visual Studio了，对于我这种从未在非GUI环境下调试过程序的人来说实在有点不爽，今天花了点时间看了一下Python自带的pdb库，发现用pdb来调试程序还是很方便的，当然了，什么远程调试，多线程之类，pdb是搞不定的。</p>
<p>用pdb调试有多种方式可选：</p>
<p>1. 命令行启动目标程序，加上-m参数，这样调用myscript.py的话断点就是程序的执行第一行之前<br />
python -m pdb myscript.py</p>
<p>2. 在Python交互环境中启用调试<br />
&gt;&gt;&gt; import pdb<br />
&gt;&gt;&gt; import mymodule<br />
&gt;&gt;&gt; pdb.run(&#8216;mymodule.test()&#8217;)</p>
<p>3. 比较常用的，就是在程序中间插入一段程序，相对于在一般IDE里面打上断点然后启动debug，不过这种方式是hardcode的</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    a = <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pdb</span>
    <span style="color: #dc143c;">pdb</span>.<span style="color: black;">set_trace</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    b = <span style="color: #ff4500;">2</span>
    c = a + b
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span></pre></div></div>

<p>然后正常运行脚本，到了pdb.set_trace()那就会定下来，就可以看到调试的提示符(Pdb)了</p>
<p>常用的调试命令</p>
<ul>
<li>h(elp)，会打印当前版本Pdb可用的命令，如果要查询某个命令，可以输入 h [command]，例如：“h l” &#8212; 查看list命令</li>
</ul>
<ul>
<li>l(ist)，可以列出当前将要运行的代码块</li>
</ul>
<p><span style="color: #008080;">(Pdb) l<br />
497             pdb.set_trace()<br />
498             base_data = {}<br />
499             new_data = {}<br />
500             try:<br />
501                 execfile(base_file_name,{},base_data)<br />
502  -&gt;             execfile(new_file_name,{},new_data)<br />
503             except:<br />
504                 logger.writeLog(“error! load result log error!”)<br />
505                 print “load cmp logs error!”<br />
506                 raise Exception, “load cmp logs error!”<br />
507 </span></p>
<ul>
<li>b(reak)， 设置断点，例如 “b 77&#8243;，就是在当前脚本的77行打上断点，还能输入函数名作为参数，断点就打到具体的函数入口，如果只敲b，会显示现有的全部断点</li>
</ul>
<p><span style="color: #008080;">(Pdb) b 504<br />
Breakpoint 4 at /home/jchen/regression/regressionLogCMP.py:504</span></p>
<ul>
<li>condition bpnumber [condition]，设置条件断点，下面语句就是对第4个断点加上条件“a==3”</li>
</ul>
<p><span style="color: #008080;">(Pdb) condition 4 a==3<br />
(Pdb) b<br />
Num Type         Disp Enb   Where<br />
4   breakpoint    keep yes at /home/jchen/regression/regressionLogCMP.py:504<br />
stop only if a==3</span></p>
<ul>
<li>cl(ear)，如果后面带有参数，就是清除指定的断点（我在Python2.4上从来没成功过！！！）；如果不带参数就是清除所有的断点</li>
</ul>
<p><span style="color: #008080;">(Pdb) cl<br />
Clear all breaks? y</span></p>
<ul>
<li>disable/enable，禁用/激活断点</li>
</ul>
<p><span style="color: #008080;">(Pdb) disable 3<br />
(Pdb) b<br />
Num Type         Disp Enb   Where<br />
3   breakpoint    keep no  at /home/jchen/regression/regressionLogCMP.py:505</span></p>
<ul>
<li>n(ext)，让程序运行下一行，如果当前语句有一个函数调用，用n是不会进入被调用的函数体中的</li>
</ul>
<p><span id="more-640"></span></p>
<ul>
<li>s(tep)，跟n相似，但是如果当前有一个函数调用，那么s会进入被调用的函数体中</li>
</ul>
<ul>
<li>c(ont(inue))，让程序正常运行，直到遇到断点</li>
</ul>
<ul>
<li>j(ump)，让程序跳转到指定的行数</li>
</ul>
<p><span style="color: #008080;">(Pdb) j 497<br />
&gt; /home/jchen/regression/regressionLogCMP.py(497)compareLog()<br />
-&gt; pdb.set_trace()</span></p>
<ul>
<li>a(rgs)，打印当前函数的参数</li>
</ul>
<p><span style="color: #008080;">(Pdb) a<br />
_logger =<br />
_base = ./base/MRM-8137.log<br />
_new = ./new/MRM-8137.log<br />
_caseid = 5550001<br />
_toStepNum = 10<br />
_cmpMap = {&#8216;_bcmpbinarylog&#8217;: &#8216;True&#8217;, &#8216;_bcmpLog&#8217;: &#8216;True&#8217;, &#8216;_bcmpresp&#8217;: &#8216;True&#8217;}</span></p>
<ul>
<li>p，最有用的命令之一，打印某个变量</li>
</ul>
<p><span style="color: #008080;">(Pdb) p _new<br />
u&#8217;./new/MRM-8137.log&#8217;</span></p>
<ul>
<li>！，感叹号后面跟着语句，可以直接改变某个变量</li>
</ul>
<ul>
<li>q(uit)，退出调试</li>
</ul>
<p>发现在命令行下调试程序也是一件挺有意思的事情，记录下来分享一下</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/python/use-pdb-debug-python/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>用Python修改含有日期的文件名</title>
		<link>http://magustest.com/blog/linux/modify-filename-using-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=modify-filename-using-python</link>
		<comments>http://magustest.com/blog/linux/modify-filename-using-python/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 10:15:35 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=587</guid>
		<description><![CDATA[问题：修要修改一些LOG FILE的名字，那些LOG FILE的文件名格式大概是 log-v0-20091012-daily-1a5019a0.csv 。需要修改红色的日期部分，把这个日期改小一点，例如改到20091001。 首先上程序： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import time, os, string, sys ONE_DAY = &#40;24 * 60 * 60&#41; if __name__ == &#34;__main__&#34;: if len&#40;sys.argv&#41;&#38;lt;2: print &#34;argv error, useage: python &#34; + __file__ + &#34; foldername int&#34; <a href='http://magustest.com/blog/linux/modify-filename-using-python/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>问题：修要修改一些LOG FILE的名字，那些LOG FILE的文件名格式大概是 log-v0-<span style="color: #ff0000;">20091012</span>-daily-1a5019a0.csv 。需要修改红色的日期部分，把这个日期改小一点，例如改到20091001。</p>
<p>首先上程序：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>, <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">string</span>, <span style="color: #dc143c;">sys</span>
ONE_DAY = <span style="color: black;">&#40;</span><span style="color: #ff4500;">24</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">&amp;</span>lt<span style="color: #66cc66;">;</span><span style="color: #ff4500;">2</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;argv error, useage: python &quot;</span> + __file__ + <span style="color: #483d8b;">&quot; foldername int&quot;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span>==<span style="color: #ff4500;">2</span>:
        intrday = <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        intrday = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    folder = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    localtime = <span style="color: #dc143c;">time</span>.<span style="color: black;">localtime</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    todate = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>localtime<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>localtime<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>localtime<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    targettime = <span style="color: #dc143c;">time</span>.<span style="color: black;">localtime</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - ONE_DAY<span style="color: #66cc66;">*</span>intrday<span style="color: black;">&#41;</span>
    newdate = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>targettime<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>targettime<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>targettime<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> folder
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #008000;">file</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>:
        newname = <span style="color: #dc143c;">string</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #008000;">file</span>, todate<span style="color: black;">&#41;</span>, newdate<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">os</span>.<span style="color: black;">rename</span><span style="color: black;">&#40;</span>folder+<span style="color: #008000;">file</span>, folder+newname<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>用的时候就是 $ python rename.py ./ 4 ；这个命令会把当前目录下面符合这个条件的文件名中的日期往前改4天，运行完了以后的文件名就是：log-v0-<span style="color: #ff0000;">20091008</span>-daily-1a5019a0.csv</p>
<p>如果还需要把文件的访问时间和修改时间也一并修改的话，那么只需要用os.utime(path, times)这个函数就好了，times是元组(Tuple)，一般可以这样用：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">time_for_utime = <span style="color: black;">&#40;</span><span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">utime</span><span style="color: black;">&#40;</span>path, time_for_utime<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/linux/modify-filename-using-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

