<?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; 自动化测试</title>
	<atom:link href="http://magustest.com/blog/tag/test-automation/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>Selenium中被误用的XPath</title>
		<link>http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wrong-xpath-in-selenium</link>
		<comments>http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 08:11:14 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[Selenium]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=852</guid>
		<description><![CDATA[用Selenium实现自动化测试的过程中，如果选择页面上的元素并且对之进行各种操作，是一个常见的任务。Selenium提供了多种定位方法： id：最有效、最方便的方法 name：跟id类似的 class name：对某些具有相同类的元素一网打尽的好方法 link text 和 partial link text： 用在定位超链接上比较多 tag name：与class name有点类似 css selector：如果你试用jQuery，这个一定是你喜欢的方法 xpath：。。。 /html/body/div/div[2]/div[2]/div[2]/div[5]/div/p[2] ？？？ 网上很多Selenium的介绍文章，在讲述如何利用XPath定位元素的时候，通常都是这样子说的“打开Firefox浏览器，安装Firebug插件，然后就能方便地获得该元素的XPath了”。由于不求甚解，在一段时间内我真以为这些看起来没什么意义，中间穿插着各种数组操作，读起来反人类反社会的所谓XPath就是真的XPath，同志们大家都被误导了。 什么是XPath：http://www.w3.org/TR/xpath/ XPath基础教程：http://www.w3schools.com/xpath/default.asp XPath在Selenium测试中有好些缺点：1. 性能差，定位元素的性能比起大多数其他方法要差；2. 不够健壮，XPath会随着页面元素布局的改变而改变；3. 兼容性不好，在不同的浏览器下对XPath的实现是不一样的。如此多的弱点，为什么它还存在于Selenium中呢？Selenium提供了这7个元素定位的工具，就好像工具箱里面有锤子有老虎钳有螺丝刀，每个工具都能完成特定的任务，前提是要在正确的前提下，正确地使用。 XPath通常会在如下场景：一个写自动化测试的人，发现他想要操作的元素不能通过id, name, link text等比较方便有效的方法来进行定位，苦逼的他没能说服开发这个页面的人把他想要的id加上，他开始用所谓的XPath来定位元素，代码中充满了各种让人摸不着头脑的XPath（/html/body/div/div[3]/div[2]/div[4]/p[2]），在我看来这样的代码跟录制出来的脚本没有任何区别。可读性差，几乎不能维护。XPath理论上可以这样使用，但是实际上应该避免这样的使用。 XPath的一些优点是大家需要知道的，例如：1. XPath可以通过某个元素找到它的祖先（Ancestors）（”/../” 或者 “ancestor-or-self::book”）；2. 可以做布尔逻辑判断，例如/button[@value=’submit’ or @name=’tijiao’] 回到上面的场景，假如说那个苦逼的人想定位到页面上的一个提交按钮，这个按钮不能通过id或者name来定位。这个时候他要做的事情不是打开Firebug定位提交按钮右击鼠标再点“Copy XPath”。而是应该是找开发把id或者name加上。如果不行，解决思路可以是：1. 找到该按钮的特征，例如按钮的文字是 submit；2. 用XPath定位，可以这样写：//button[@value='submit']。  我个人对使用XPath比较反感的，如果可能的话，尽可能使用id或者name。真的要用XPath，千万千万不要打开Firebug定位提交按钮右击鼠标再点“Copy XPath”。先认真学习XPath，后使用。在很长一段时间里面，我对XPath真的是恨之入骨，恨不得先杀之而后快，但是想到存在就是合理，那么多大牛们都没有把XPath摒弃与Selenium之外，XPath必然有它的价值。最近花了点时间学习了一下XPath，并且读了一些关于如何在Selenium里面正确使用XPath的文章，豁然开朗。 参考文章： http://www.theautomatedtester.co.uk/tutorials/selenium/selenium_xpath.htm http://wiki.openqa.org/display/SEL/Help+With+XPath http://stackoverflow.com/questions/5808909/selecting-an-element-with-xpath-and-selenium https://community.neustar.biz/community/wpm/blog/2009/04/30/test-your-selenium-xpath-easily-with-firebug http://automationtricks.blogspot.com/2010/09/how-to-use-functions-in-xpath-in.html Related posts: WebDriver <a href='http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/' 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/sst-selenium-simple-test/' rel='bookmark' title='SST (selenium-simple-test) 介绍'>SST (selenium-simple-test) 介绍</a></li>
<li><a href='http://magustest.com/blog/webdriver/webdriver-screenshot-on-exception/' rel='bookmark' title='WebDriver测试失败后自动获取截图'>WebDriver测试失败后自动获取截图</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>用<a href="http://seleniumhq.org/" target="_blank">Selenium</a>实现自动化测试的过程中，如果选择页面上的元素并且对之进行各种操作，是一个常见的任务。Selenium提供了多种定位方法：</p>
<ul>
<li>id：最有效、最方便的方法</li>
<li>name：跟id类似的</li>
<li>class name：对某些具有相同类的元素一网打尽的好方法</li>
<li>link text 和 partial link text： 用在定位超链接上比较多</li>
<li>tag name：与class name有点类似</li>
<li>css selector：如果你试用jQuery，这个一定是你喜欢的方法</li>
<li><strong>xpath：。。。 /html/body/div/div[2]/div[2]/div[2]/div[5]/div/p[2] ？？？</strong></li>
</ul>
<p>网上很多Selenium的介绍文章，在讲述如何利用<a href="http://www.w3.org/TR/xpath/" target="_blank">XPath</a>定位元素的时候，通常都是这样子说的“打开Firefox浏览器，安装Firebug插件，然后就能方便地获得该元素的XPath了”。由于不求甚解，在一段时间内我真以为这些看起来没什么意义，中间穿插着各种数组操作，读起来反人类反社会的所谓XPath就是真的XPath，同志们大家都被误导了。</p>
<p>什么是XPath：<a href="http://www.w3.org/TR/xpath/" target="_blank">http://www.w3.org/TR/xpath/</a><br />
XPath基础教程：<a href="http://www.w3schools.com/xpath/default.asp" target="_blank">http://www.w3schools.com/xpath/default.asp</a></p>
<p>XPath在Selenium测试中有好些缺点：1. 性能差，定位元素的性能比起大多数其他方法要差；2. 不够健壮，XPath会随着页面元素布局的改变而改变；3. 兼容性不好，在不同的浏览器下对XPath的实现是不一样的。如此多的弱点，为什么它还存在于Selenium中呢？Selenium提供了这7个元素定位的工具，就好像工具箱里面有锤子有老虎钳有螺丝刀，每个工具都能完成特定的任务，前提是要在正确的前提下，正确地使用。</p>
<p>XPath通常会在如下场景：一个写自动化测试的人，发现他想要操作的元素不能通过id, name, link text等比较方便有效的方法来进行定位，苦逼的他没能说服开发这个页面的人把他想要的id加上，他开始用所谓的XPath来定位元素，代码中充满了各种让人摸不着头脑的XPath（/html/body/div/div[3]/div[2]/div[4]/p[2]），在我看来这样的代码跟录制出来的脚本没有任何区别。可读性差，几乎不能维护。XPath理论上可以这样使用，但是实际上应该避免这样的使用。</p>
<p>XPath的一些优点是大家需要知道的，例如：1. XPath可以通过某个元素找到它的祖先（Ancestors）（”/../” 或者 “ancestor-or-self::book”）；2. 可以做布尔逻辑判断，例如/button[@value=’submit’ or @name=’tijiao’]</p>
<p>回到上面的场景，假如说那个苦逼的人想定位到页面上的一个提交按钮，这个按钮不能通过id或者name来定位。这个时候他要做的事情不是打开Firebug定位提交按钮右击鼠标再点“Copy XPath”。而是应该是找开发把id或者name加上。如果不行，解决思路可以是：1. 找到该按钮的特征，例如按钮的文字是 submit；2. 用XPath定位，可以这样写：//button[@value='submit']。<br />
<br />
我个人对使用XPath比较反感的，如果可能的话，尽可能使用id或者name。真的要用XPath，<strong>千万千万不要打开Firebug定位提交按钮右击鼠标再点“Copy XPath”</strong>。先认真学习XPath，后使用。在很长一段时间里面，我对XPath真的是恨之入骨，恨不得先杀之而后快，但是想到存在就是合理，那么多大牛们都没有把XPath摒弃与Selenium之外，XPath必然有它的价值。最近花了点时间学习了一下XPath，并且读了一些关于如何在Selenium里面正确使用XPath的文章，豁然开朗。</p>
<p>参考文章：</p>
<ul>
<li><a href="http://www.theautomatedtester.co.uk/tutorials/selenium/selenium_xpath.htm" target="_blank">http://www.theautomatedtester.co.uk/tutorials/selenium/selenium_xpath.htm</a></li>
<li><a href="http://wiki.openqa.org/display/SEL/Help+With+XPath" target="_blank">http://wiki.openqa.org/display/SEL/Help+With+XPath</a></li>
<li><a href="http://stackoverflow.com/questions/5808909/selecting-an-element-with-xpath-and-selenium" target="_blank">http://stackoverflow.com/questions/5808909/selecting-an-element-with-xpath-and-selenium</a></li>
<li><a href="https://community.neustar.biz/community/wpm/blog/2009/04/30/test-your-selenium-xpath-easily-with-firebug" target="_blank">https://community.neustar.biz/community/wpm/blog/2009/04/30/test-your-selenium-xpath-easily-with-firebug</a></li>
<li><a href="http://automationtricks.blogspot.com/2010/09/how-to-use-functions-in-xpath-in.html" target="_blank">http://automationtricks.blogspot.com/2010/09/how-to-use-functions-in-xpath-in.html</a></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/sst-selenium-simple-test/' rel='bookmark' title='SST (selenium-simple-test) 介绍'>SST (selenium-simple-test) 介绍</a></li>
<li><a href='http://magustest.com/blog/webdriver/webdriver-screenshot-on-exception/' rel='bookmark' title='WebDriver测试失败后自动获取截图'>WebDriver测试失败后自动获取截图</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/wrong-xpath-in-selenium/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<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>Hudson保存WebDriver测试执行失败的截图</title>
		<link>http://magustest.com/blog/automationtesting/archive-webdriver-screenshot/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=archive-webdriver-screenshot</link>
		<comments>http://magustest.com/blog/automationtesting/archive-webdriver-screenshot/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 09:42:18 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[WebDriver]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=802</guid>
		<description><![CDATA[之前一篇文章介绍了如何把remote driver出错时候的截图保存下来，今天分享一下在Hudson下如何把这些截图保存下来。 用Hudson来跑自动化测试，其实就是把运行自动化测试看作是构建一个软件。在Hudson里面有一个功能叫“Archive the artifacts”，可以把构建的产物（就是所谓的artifacts）打包。具体做法就是 在Build的最后添加一个步骤，把所有测试过程中生成的.png文件，拷贝到workspace。并且记得删掉原图，要不然下一次测试还是会把之前出错的截图也一起打包 勾上“Archive the artifacts” 在“Files to archive”里面填“*.png” 如果你的测试每次都有异常，那么恭喜你（What？？？），这个build会跑的很顺利。因为每次都有一些.png文件生成，每次打包都能找到一些.png。但是如果有一天，你的自动化测试或者被测系统变得健康起来了，没有错误了，那就会遇到一些麻烦。 作为一个持续构建工具，Hudson会认为，所有build都是理所当然地有一些artifacts。如果没有任何artifacts生成，那做这个build干吗？当测试都顺利跑过，没有生成错误截图的.png文件的时候，这个build也会fail，因为打包的时候没有找到任何文件。这个时候可以这样做。 在Build的最后一步再加一个步骤，在workspace目录中随便生成一个.png文件，例如“touch pass.png” 直接在Ant脚本里面添加一个任务，&#60;touch file=”pass.png”&#62; No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>之前一篇文章介绍了<a title="WebDriver测试失败后自动获取截图" href="http://magustest.com/blog/webdriver/webdriver-screenshot-on-exception/" target="_blank">如何把remote driver出错时候的截图保存下来</a>，今天分享一下在Hudson下如何把这些截图保存下来。</p>
<p>用Hudson来跑自动化测试，其实就是把运行自动化测试看作是构建一个软件。在Hudson里面有一个功能叫“Archive the artifacts”，可以把构建的产物（就是所谓的artifacts）打包。具体做法就是</p>
<ol>
<li>在Build的最后添加一个步骤，把所有测试过程中生成的.png文件，拷贝到workspace。并且记得删掉原图，要不然下一次测试还是会把之前出错的截图也一起打包</li>
<li>勾上“Archive the artifacts”</li>
<li>在“Files to archive”里面填“*.png”</li>
</ol>
<div>如果你的测试每次都有异常，那么恭喜你（What？？？），这个build会跑的很顺利。因为每次都有一些.png文件生成，每次打包都能找到一些.png。但是如果有一天，你的自动化测试或者被测系统变得健康起来了，没有错误了，那就会遇到一些麻烦。</div>
<div>作为一个持续构建工具，Hudson会认为，所有build都是理所当然地有一些artifacts。如果没有任何artifacts生成，那做这个build干吗？当测试都顺利跑过，没有生成错误截图的.png文件的时候，这个build也会fail，因为打包的时候没有找到任何文件。这个时候可以这样做。</div>
<div>
<ul>
<li>在Build的最后一步再加一个步骤，在workspace目录中随便生成一个.png文件，例如“touch pass.png”</li>
<li>直接在Ant脚本里面添加一个任务，&lt;touch file=”pass.png”&gt;</li>
</ul>
</div>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/archive-webdriver-screenshot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hudson + WebDriver 组织自动化测试</title>
		<link>http://magustest.com/blog/automationtesting/hudson-webdriver-selenium/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hudson-webdriver-selenium</link>
		<comments>http://magustest.com/blog/automationtesting/hudson-webdriver-selenium/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 01:42:48 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[TestNG]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=793</guid>
		<description><![CDATA[之前介绍过如何使用TestNG来驱动WebDriver，用Ant来自动化运行测试。今天分享一下如何把这些东西都放到Hudson（Jenkins也行）里面呢？ Hudson是一个比较流行都持续集成工具。用Hudson来驱动自动化测试的好处有以下这些： 类似crontab的自动任务管理 丰富的插件支持 支持分布式任务 容易部署 其实整个过程很简单，把Hudson跑起来，新建一个Job，配置一下Ant任务就好了。这里只分享一下我遇到的一些坑。 是否使用Source Code Management获取最新的测试代码？ 如果每次测试都拉最新的代码，好处就是保证测试代码是最新的。但是也会带来一些问题，测试代码本身也是代码，怎么保证最新的测试代码没有问题呢？我个人认为，如果团队比较小，可以直接拉最新的代码；如果团队大，需要控制。 如果不用SCM插件，怎么样更新自动化测试代码？ 我想到的一种办法就是，在Hudson里面建立一个构建自动化测试代码的Job，这个Job的产物就是自动化测试的包，譬如说如果用WebDriver或者Selenium，就把测试代码build成一个或者若干个jar包，然后建立一个latest的软链接指向最新的jar包；在运行自动化测试的Job里面做好配置，运行测试的目标jar包就指向latest.jar就OK了。 TestNG的结果如何跟Hudson整合 Hudson插件很多，可以用testng-plugin来完成这个任务。配置比较简单，在Ant脚本里面配置好TestNG的result output，然后在Hudson里面把测试报告的模式填好。我直接填的TestNG的默认结果文件“testng-results.xml”。build.xml节点配置的一个例子： &#60;target name=&#34;live_check&#34; depends=&#34;compile,remove_last_result&#34;&#62; &#60;testng outputdir=&#34;${testng.output.dir}&#34; classpathref=&#34;classes&#34; delegateCommandSystemProperties=&#34;true&#34; useDefaultListeners=&#34;true&#34;&#62; &#60;xmlfileset dir=&#34;${base.dir}&#34; includes=&#34;${live.check.config}&#34;/&#62; &#60;/testng&#62; &#60;move file=&#34;${testng.output.dir}/${test.result.file}&#34; todir=&#34;${ci.workspace}&#34;/&#62; &#60;/target&#62; 首先在testng节点指定outputdir属性，然后测试运行完成以后把结果文件移动到Hudson的workspace 怎么样把Ant的参数传递给TestNG 很多时候我们会希望通过ant把一些参数传递给testng.xml，从而使得测试更加灵活。例如传递不用的base_url可以测试不同的站点。还有配置不同的浏览器。虽然之前这篇文章已经介绍了如何把Ant的参数传递给TestNG，但是那个方法有个缺点，如果在测试方法A里面调用了测试方法B，测试方法B是不能拿到Ant传进去的参数的。我的办法比较土，就是首先写好一个testng_base.xml的模板文件，把一些可能经常改变的数值替换成参数，然后用Ant的replace任务做字符串替换。 &#60;target name=&#34;replace_testng_xml&#34;&#62; &#60;replace file=&#34;${base.dir}/${testng.file}&#34; token=&#34;@@base_url@@&#34; value=&#34;${base_url}&#34;/&#62; &#60;replace file=&#34;${base.dir}/${testng.file}&#34; token=&#34;@@browser@@&#34; value=&#34;${webdriver.browser}&#34;/&#62; &#60;/target&#62; No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>之前介绍过如何<a title="WebDriver + TestNG 应用" href="http://magustest.com/blog/automationtesting/webdriver-testng/" target="_blank">使用TestNG来驱动WebDriver</a>，<a title="TestNG+Ant自动运行测试" href="http://magustest.com/blog/automationtesting/testng-ant/" target="_blank">用Ant来自动化运行测试</a>。今天分享一下如何把这些东西都放到<a href="http://hudson-ci.org/" target="_blank">Hudson</a>（<a href="http://jenkins-ci.org/" target="_blank">Jenkins也行</a>）里面呢？</p>
<p>Hudson是一个比较流行都持续集成工具。用Hudson来驱动自动化测试的好处有以下这些：</p>
<ul>
<li>类似crontab的自动任务管理</li>
<li>丰富的插件支持</li>
<li>支持分布式任务</li>
<li>容易部署</li>
</ul>
<p>其实整个过程很简单，把Hudson跑起来，新建一个Job，配置一下Ant任务就好了。这里只分享一下我遇到的一些坑。</p>
<h2>是否使用Source Code Management获取最新的测试代码？</h2>
<p>
如果每次测试都拉最新的代码，好处就是保证测试代码是最新的。但是也会带来一些问题，测试代码本身也是代码，怎么保证最新的测试代码没有问题呢？我个人认为，如果团队比较小，可以直接拉最新的代码；如果团队大，需要控制。</p>
<h2>如果不用SCM插件，怎么样更新自动化测试代码？</h2>
<p>我想到的一种办法就是，在Hudson里面建立一个构建自动化测试代码的Job，这个Job的产物就是自动化测试的包，譬如说如果用WebDriver或者Selenium，就把测试代码build成一个或者若干个jar包，然后建立一个latest的软链接指向最新的jar包；在运行自动化测试的Job里面做好配置，运行测试的目标jar包就指向latest.jar就OK了。</p>
<h2>TestNG的结果如何跟Hudson整合</h2>
<p>Hudson插件很多，可以用<a href="http://wiki.hudson-ci.org/display/HUDSON/testng-plugin" target="_blank">testng-plugin</a>来完成这个任务。配置比较简单，在Ant脚本里面配置好TestNG的result output，然后在Hudson里面把测试报告的模式填好。我直接填的TestNG的默认结果文件“testng-results.xml”。build.xml节点配置的一个例子：</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;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;live_check&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;compile,remove_last_result&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;testng</span> <span style="color: #000066;">outputdir</span>=<span style="color: #ff0000;">&quot;${testng.output.dir}&quot;</span> <span style="color: #000066;">classpathref</span>=<span style="color: #ff0000;">&quot;classes&quot;</span> <span style="color: #000066;">delegateCommandSystemProperties</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">useDefaultListeners</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xmlfileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${base.dir}&quot;</span> <span style="color: #000066;">includes</span>=<span style="color: #ff0000;">&quot;${live.check.config}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/testng<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;move</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${testng.output.dir}/${test.result.file}&quot;</span> <span style="color: #000066;">todir</span>=<span style="color: #ff0000;">&quot;${ci.workspace}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>首先在testng节点指定outputdir属性，然后测试运行完成以后把结果文件移动到Hudson的workspace</p>
<h2>怎么样把Ant的参数传递给TestNG</h2>
<p>很多时候我们会希望通过ant把一些参数传递给testng.xml，从而使得测试更加灵活。例如传递不用的base_url可以测试不同的站点。还有配置不同的浏览器。虽然之前这篇文章已经介绍了<a title="TestNG+Ant自动运行测试" href="http://magustest.com/blog/automationtesting/testng-ant/" target="_blank">如何把Ant的参数传递给TestNG</a>，但是那个方法有个缺点，如果在测试方法A里面调用了测试方法B，测试方法B是不能拿到Ant传进去的参数的。我的办法比较土，就是首先写好一个testng_base.xml的模板文件，把一些可能经常改变的数值替换成参数，然后用Ant的replace任务做字符串替换。</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;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;replace_testng_xml&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;replace</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${base.dir}/${testng.file}&quot;</span> <span style="color: #000066;">token</span>=<span style="color: #ff0000;">&quot;@@base_url@@&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${base_url}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;replace</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${base.dir}/${testng.file}&quot;</span> <span style="color: #000066;">token</span>=<span style="color: #ff0000;">&quot;@@browser@@&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${webdriver.browser}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/hudson-webdriver-selenium/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TestNG+Ant自动运行测试</title>
		<link>http://magustest.com/blog/automationtesting/testng-ant/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=testng-ant</link>
		<comments>http://magustest.com/blog/automationtesting/testng-ant/#comments</comments>
		<pubDate>Sat, 20 Aug 2011 16:39:27 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[TestNG]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=779</guid>
		<description><![CDATA[之前一篇博客分享了如何使用WebDriver+TestNG实现UI自动化，现在就要让自动化测试自己跑起来，不需要人工干预。需要用到Ant，以及一些定时任务工具，例如Linux的crontab。 如何在Ant的build.xml里面正确配置TestNG呢？ 1. 在build.xml里面定义testng任务，在classpath里面指定testng.jar &#60;taskdef resource=&#34;testngtasks&#34; classpath=&#34;${3rd.lib.dir}/testng.jar&#34;/&#62; 2. 在build.xml里面新建一个 叫regression的target &#60;project basedir=&#34;.&#34; default=&#34;regression&#34; name=&#34;automation test&#34;&#62; &#60;property name=&#34;base.dir&#34; value=&#34;/home/maguschen/workspaces/automation&#34;/&#62; &#60;property name=&#34;testng.output.dir&#34; value=&#34;${base.dir}/test-output&#34;/&#62; &#60;property name=&#34;3rd.lib.dir&#34; value=&#34;${base.dir}/libs&#34;/&#62; &#60;property name=&#34;testng.file&#34; value=&#34;testng.xml&#34;/&#62; &#160; &#60;taskdef resource=&#34;testngtasks&#34; classpath=&#34;${3rd.lib.dir}/testng.jar&#34;/&#62; &#160; &#60;target name=&#34;clean&#34;&#62; &#60;delete dir=&#34;${base.dir}/bin&#34;/&#62; &#60;/target&#62; &#60;target name=&#34;compile&#34; depends=&#34;clean&#34;&#62; &#60;mkdir dir=&#34;${base.dir}/bin&#34;/&#62; &#60;javac srcdir=&#34;${base.dir}/src&#34; destdir=&#34;${base.dir}/bin&#34; classpathref=&#34;classes&#34; includeantruntime=&#34;off&#34; debug=&#34;on&#34; debuglevel=&#34;lines,vars,source&#34;/&#62; &#60;/target&#62; &#160; &#60;path id=&#34;classes&#34;&#62; &#60;fileset dir=&#34;${3rd.lib.dir}&#34; <a href='http://magustest.com/blog/automationtesting/testng-ant/' class='excerpt-more'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>之前一篇博客分享了如何<a title="WebDriver + TestNG 应用" href="http://magustest.com/blog/automationtesting/webdriver-testng/" target="_blank">使用WebDriver+TestNG实现UI自动化</a>，现在就要让自动化测试自己跑起来，不需要人工干预。需要用到<a title="Ant" href="http://ant.apache.org/" target="_blank">Ant</a>，以及一些定时任务工具，例如Linux的crontab。</p>
<p>如何在Ant的build.xml里面正确配置TestNG呢？</p>
<p>1. 在build.xml里面定义testng任务，在classpath里面指定testng.jar</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;taskdef</span> <span style="color: #000066;">resource</span>=<span style="color: #ff0000;">&quot;testngtasks&quot;</span> <span style="color: #000066;">classpath</span>=<span style="color: #ff0000;">&quot;${3rd.lib.dir}/testng.jar&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>2. 在build.xml里面新建一个 叫regression的target</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;project</span> <span style="color: #000066;">basedir</span>=<span style="color: #ff0000;">&quot;.&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;regression&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;automation test&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;base.dir&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;/home/maguschen/workspaces/automation&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;testng.output.dir&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${base.dir}/test-output&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;3rd.lib.dir&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${base.dir}/libs&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;testng.file&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;testng.xml&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;taskdef</span> <span style="color: #000066;">resource</span>=<span style="color: #ff0000;">&quot;testngtasks&quot;</span> <span style="color: #000066;">classpath</span>=<span style="color: #ff0000;">&quot;${3rd.lib.dir}/testng.jar&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;clean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;delete</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${base.dir}/bin&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;compile&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;clean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mkdir</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${base.dir}/bin&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;javac</span> <span style="color: #000066;">srcdir</span>=<span style="color: #ff0000;">&quot;${base.dir}/src&quot;</span> <span style="color: #000066;">destdir</span>=<span style="color: #ff0000;">&quot;${base.dir}/bin&quot;</span> <span style="color: #000066;">classpathref</span>=<span style="color: #ff0000;">&quot;classes&quot;</span> <span style="color: #000066;">includeantruntime</span>=<span style="color: #ff0000;">&quot;off&quot;</span> <span style="color: #000066;">debug</span>=<span style="color: #ff0000;">&quot;on&quot;</span> <span style="color: #000066;">debuglevel</span>=<span style="color: #ff0000;">&quot;lines,vars,source&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;path</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;classes&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${3rd.lib.dir}&quot;</span> <span style="color: #000066;">includes</span>=<span style="color: #ff0000;">&quot;*jar&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${3rd.lib.dir}&quot;</span> <span style="color: #000066;">includes</span>=<span style="color: #ff0000;">&quot;*zip&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathelement</span> <span style="color: #000066;">location</span>=<span style="color: #ff0000;">&quot;${base.dir}/bin&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/path<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;regression&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;compile&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;testng</span> <span style="color: #000066;">outputdir</span>=<span style="color: #ff0000;">&quot;${testng.output.dir}&quot;</span> <span style="color: #000066;">classpathref</span>=<span style="color: #ff0000;">&quot;classes&quot;</span> <span style="color: #000066;">delegateCommandSystemProperties</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xmlfileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${base.dir}&quot;</span> <span style="color: #000066;">includes</span>=<span style="color: #ff0000;">&quot;${testng.file}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/testng<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>在target里面新建一个testng标签，里面需要设置的属性有：outputdir &#8211; 测试结果输出目录；classpathref &#8211; 那些自动化测试代码的目标路径，通常就是编译完成以后的那个目标路径，例如xxx/bin；delegateCommandSystemProperties &#8211; 接受传递命令行参数作为系统变量，这个设置为true可以在调用Ant的时候通过 -Dfoo=value 把参数传递给TestNG；里面还有一个xmlfileset节点，这个节点就是指定testng.xml文件的目录以及具体文件。</p>
<p>regression 的 target 有一个depends属性，意思就是跑regression之前需要做compile，而跑compile之前需要clean，应该很容易理解。直接在命令行里面运行：</p>
<blockquote><p>ant -Durl=http://www.google.com -f build.xml regression
</p></blockquote>
<p>这里出现了 -Durl=http://www.google.com ，回到之前的配置，delegateCommandSystemProperties=”true”。如果这个参数为true，那么通过命令行的 -D 参数可以把一些变量传递给TestNG。譬如说TestNG的测试方法里面是有@Parameters({“url”})标签的话，就能通过ant -Durl=xxx 来传递url的值给到TestNG。例如</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Parameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;url&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
@Test
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> search<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> url<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    WebDriver driver <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FirefoxDriver<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    driver.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    WebElement query <span style="color: #339933;">=</span> driver.<span style="color: #006633;">findElement</span><span style="color: #009900;">&#40;</span>By.<span style="color: #006633;">name</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;q&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    query.<span style="color: #006633;">sendKeys</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Cheese&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    query.<span style="color: #006633;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>如果这样调用：ant -Durl=http://www.google.com -f build regression  。那么就会进入google的首页搜索，如果是： ant -Durl=http://magustest.com -f build regression ，那么就会找不到叫“q”的元素，呵呵。</p>
<p>接下来只要把cron job配好就完成了</p>
<blockquote><p>15 * * * * ant -f /home/maguschen/workspaces/automation/build.xml regression</p></blockquote>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/testng-ant/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WebDriver + TestNG 应用</title>
		<link>http://magustest.com/blog/automationtesting/webdriver-testng/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=webdriver-testng</link>
		<comments>http://magustest.com/blog/automationtesting/webdriver-testng/#comments</comments>
		<pubDate>Sat, 20 Aug 2011 10:14:00 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[WebDriver]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[TestNG]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=763</guid>
		<description><![CDATA[Selenium 2 已经发布了一个多月，官方版本已经到了Selenium 2.3，并且在Google code里面可以找到2.4的下载。Selenium 2 最大的更新就是集成了WebDriver。这两者是什么关系呢？如果你搜索WebDriver，第一条结果是Selenium。其实WebDriver和Selenium可以说是在实现UI Automation的竞争对手。Selenium是运行在JavaScript的sandbox里面，所以很容易就支持不同的浏览器；而WebDriver则是直接操作浏览器本身，更接近用户的真实操作，但正因为如此，所以WebDriver在多浏览器/操作系统的支持上就要落后于Selenium。不过从Selenium 2开始，这两个项目合并了，可以继续用原来的Selenium，也可以考虑迁移到WebDriver。我个人认为WebDriver应该是以后的大趋势，还是值得迁移的。至于你信不信，我反正是信了。 作为一个轻量级的UI Automation框架，需要写一些驱动它的代码，大部分人会选择JUnit，因为JUnit是单元测试的事实标准；但是我会用TestNG。这些UI Automation的东西，它们本身不是单元测试，而且也没有太多单元测试的风格。 从一段简单的测试开始 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class GoogleTest &#123; @Test public void search&#40;ITestContext context&#41; &#123; WebDriver driver = new FirefoxDriver&#40;&#41;; &#160; driver.get&#40;&#34;http://www.google.com&#34;&#41;; &#160; WebElement element = driver.findElement&#40;By.name&#40;&#34;q&#34;&#41;&#41;; &#160; element.sendKeys&#40;&#34;magus&#34;&#41;; element.submit&#40;&#41;; &#160; Assert.assertTrue&#40;driver.getTitle&#40;&#41;.contains&#40;&#34;magus&#34;&#41;, <a href='http://magustest.com/blog/automationtesting/webdriver-testng/' class='excerpt-more'>[...]</a>
Related posts:<ol>
<li><a href='http://magustest.com/blog/automationtesting/testng-ant/' rel='bookmark' title='TestNG+Ant自动运行测试'>TestNG+Ant自动运行测试</a></li>
<li><a href='http://magustest.com/blog/automationtesting/hudson-webdriver-selenium/' rel='bookmark' title='Hudson + WebDriver 组织自动化测试'>Hudson + WebDriver 组织自动化测试</a></li>
<li><a href='http://magustest.com/blog/webdriver/webdriver-screenshot-on-exception/' rel='bookmark' title='WebDriver测试失败后自动获取截图'>WebDriver测试失败后自动获取截图</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a title="selenium 2 发布" href="http://seleniumhq.wordpress.com/2011/07/08/selenium-2-0/" target="_blank">Selenium 2 已经发布</a>了一个多月，官方版本已经到了<a title="Selenium 2.3 发布" href="http://seleniumhq.wordpress.com/2011/08/02/selenium-2-3-released/" target="_blank">Selenium 2.3</a>，并且在<a title="Selenium download" href="http://code.google.com/p/selenium/downloads/list" target="_blank">Google code里面可以找到2.4</a>的下载。Selenium 2 最大的更新就是集成了WebDriver。这两者是什么关系呢？如果你搜索WebDriver，第一条结果是Selenium。其实WebDriver和Selenium可以说是在实现UI Automation的竞争对手。Selenium是运行在JavaScript的sandbox里面，所以很容易就支持不同的浏览器；而WebDriver则是直接操作浏览器本身，更接近用户的真实操作，但正因为如此，所以WebDriver在多浏览器/操作系统的支持上就要落后于Selenium。不过从Selenium 2开始，这两个项目合并了，可以继续用原来的Selenium，也可以考虑迁移到WebDriver。我个人认为WebDriver应该是以后的大趋势，还是值得迁移的。至于你信不信，我反正是信了。</p>
<p>作为一个轻量级的UI Automation框架，需要写一些驱动它的代码，大部分人会选择JUnit，因为JUnit是单元测试的事实标准；但是我会用<a title="TestNG" href="http://testng.org/" target="_blank">TestNG</a>。这些UI Automation的东西，它们本身不是单元测试，而且也没有太多单元测试的风格。</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
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> GoogleTest  <span style="color: #009900;">&#123;</span>
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> search<span style="color: #009900;">&#40;</span>ITestContext context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        WebDriver driver <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FirefoxDriver<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        driver.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;http://www.google.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        WebElement element <span style="color: #339933;">=</span> driver.<span style="color: #006633;">findElement</span><span style="color: #009900;">&#40;</span>By.<span style="color: #006633;">name</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;q&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        element.<span style="color: #006633;">sendKeys</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;magus&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        element.<span style="color: #006633;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertTrue</span><span style="color: #009900;">&#40;</span>driver.<span style="color: #006633;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;magus&quot;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;Something wrong with title&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                           
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>TestNG应用了Java的Annotations，只需要在测试方法上面打上@Test就可以标示出search是一个测试方法。用TestNG运行测试还需要一个testng.xml的文件，文件名其实可以随便起，没有关系的。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;suite</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Magus demo&quot;</span> <span style="color: #000066;">verbose</span>=<span style="color: #ff0000;">&quot;2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Search function&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;test.GoogleTest&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;search&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/suite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>我想让测试更加灵活，1. 可以配置使用任意支持的浏览器进行测试；2. 配置所有Google的URL；3. 配置搜索的关键字。修改后的代码：</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
20
21
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> GoogleTest  <span style="color: #009900;">&#123;</span>
    WebDriver driver<span style="color: #339933;">;</span>
&nbsp;
    @Parameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;browser&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    @BeforeTest
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setupBrowser<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> browser<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>browser.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;firefox&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            driver <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FirefoxDriver<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
            driver <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ChromeDriver<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>   
    <span style="color: #009900;">&#125;</span>   
&nbsp;
    @Parameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;url&quot;</span>, <span style="color: #0000ff;">&quot;keyword&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> search<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> url, <span style="color: #003399;">String</span> keyword, ITestContext context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>        driver.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        WebElement element <span style="color: #339933;">=</span> driver.<span style="color: #006633;">findElement</span><span style="color: #009900;">&#40;</span>By.<span style="color: #006633;">name</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;q&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        element.<span style="color: #006633;">sendKeys</span><span style="color: #009900;">&#40;</span>keyword<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        element.<span style="color: #006633;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertTrue</span><span style="color: #009900;">&#40;</span>driver.<span style="color: #006633;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span>keyword<span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;Something wrong with title&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>        <span style="color: #009900;">&#125;</span>   
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>testng.xml</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
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;suite</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Magus demo&quot;</span> <span style="color: #000066;">verbose</span>=<span style="color: #ff0000;">&quot;2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;browser&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;firefox&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;http://www.google.com&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;keyword&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;magus&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Search function&quot;</span> <span style="color: #000066;">preserve-order</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;test.GoogleTest&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;setupBrowser&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;search&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/suite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>利用TestNG的@Parameters标签，让测试方法从testng.xml里面读取参数，实现参数化。在testng.xml的配置中，test节点需要增加一个属性的配置： preserve-order=”true”。这个preserve-order默认是false，在<methods>节点下面的所有方法的执行顺序是无序的。把它设为true以后就能保证在<methods>节点下的方法是按照顺序执行的。TestNG的这个功能可以方便我们在testng.xml里面拼装测试。假设我们有很多独立的测试方法，例如</p>
<ul>
<li>navigateCategory</li>
<li>addComment</li>
<li>addFriend</li>
<li>login</li>
<li>logout</li>
</ul>
<p>就可以在testng.xml里面拼出不同的测试，例如</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
20
21
22
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Add friend&quot;</span> <span style="color: #000066;">preserve-order</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;test.GoogleTest&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;login&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;addFriend&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;logout&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Add comment to category&quot;</span> <span style="color: #000066;">preserve-order</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;test.GoogleTest&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;login&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;navigateCategory&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;addComment&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;logout&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/methods<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>TestNG比JUnit更加适合做一些非单元测试的事情，不是说JUnit不好，而是不能把JUnit当成万能的锤子，到处钉钉子。WebDriver的API比Selenium的更加简洁，会是以后的大趋势。</p>
<p>之后打算分享一下如何用ant把自动化测试自动化起来。</p>
<p>Related posts:<ol>
<li><a href='http://magustest.com/blog/automationtesting/testng-ant/' rel='bookmark' title='TestNG+Ant自动运行测试'>TestNG+Ant自动运行测试</a></li>
<li><a href='http://magustest.com/blog/automationtesting/hudson-webdriver-selenium/' rel='bookmark' title='Hudson + WebDriver 组织自动化测试'>Hudson + WebDriver 组织自动化测试</a></li>
<li><a href='http://magustest.com/blog/webdriver/webdriver-screenshot-on-exception/' rel='bookmark' title='WebDriver测试失败后自动获取截图'>WebDriver测试失败后自动获取截图</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/webdriver-testng/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>敏捷开发中开展自动化测试的经验</title>
		<link>http://magustest.com/blog/agile-testing/automation-testing-in-agile/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automation-testing-in-agile</link>
		<comments>http://magustest.com/blog/agile-testing/automation-testing-in-agile/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 16:19:36 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[敏捷测试]]></category>
		<category><![CDATA[自动化测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=673</guid>
		<description><![CDATA[上周在51testing上看到一个问题，题目是在敏捷开发中，自动化测试应该如何开展呢？当时在论坛上回复了一下，现在放到博客，稍微调整一下。 首先，敏捷开发并不是部分同学想象中的那样，没有文档没有需求，开发来了就干，干几个月就丢给客户一个版本让他们用去。我们公司一般6个星期是一个release周期，在这6个星期里面，可以做的事情是非常多的。 需求，需求通常来自于PM，在一个release周期的开始，QA通常没太多事情需要做，比较轻松，这个时候一个比较重要的工作就是跟PM沟通当前release里面的一些feature的情况。在这个时候，QA可以做一些自动化测试的准备。例如在某个release周期里，我知道在接下来的测试当中我需要频繁地比较CSV文件，那么作为QA就应该在项目还不是很紧张的时候，就开始准备自动化测试的脚本，例如刚才说的这个CSV文件比较工作。 开始开发，如果公司是实时TDD开发，那么这个时候QA可以做的事情大概有2个，帮助开发写单元测试用例，并且实施自动化测试（主要是单元测试），另一个是review（虽然不是自动化测试的内容）。如果不是采用TDD开发，那么QA做的事情跟上一个阶段的做的差不多。 正式提交测试，OK，这个时候是我们QA比较忙的时候，有可能出现几个情况，1. 跟我的预想一样，我真的需要一个CSV文件比较工作，并且只需要这一个工具，并且我已经完成了，那么就可以进行测试了。2. 可能有一些新的自动化测试需求跑出来了，例如每天晚上自动比较几万个CSV文件并且把测试结果发给相关的人，这时候作为QA，在考虑资源允许的情况下，应该尽早完成这个工具，而不是每天晚上爬起来看结果。 发布完毕以后，回过头来看工具，是否有值得改进的地方，是否能够改进一下就能够给整个Team使用。 以上算是一个release周期里面的一些微观的工作，宏观上来说需要做点什么事情呢？ 现在提到的敏捷开发，都有一个很突出的特点，就是产品快速交付给客户，为了快速交付这个目的，公司里面每个团队都作出了努力，那么具体到QA团队，肯定就是要在保持测试质量得到保证的前提下，尽可能地缩减测试所需要的时间，使得产品按时按质交付。要达到这个目的，总靠一些AD-HOC的工作（例如刚才提到的突然写个CSV比较工具）是不可能达到要求的，那应该如何进行呢？ 敏捷开发也是开发，产品不是孙悟空，不会某一天就从石头里面爆出来了。在产品开发的前期（例如0.1, 0.2版本之类），尽可能地想办法搭建一个自动化回归测试的框架，这个框架的特点有：1. 快速完成回归测试； 2.能够快速地添加测试用例并且跑起来；3.能够随着产品的演化而不断改进（不能是那种用1~2个release就要扔的东西）；4.维护的成本要低（在一个release周期里面如果自动化测试需求有变化，不应该需要超过1个星期的时间才能改好，当然翻天覆地的变化除外） 综上所述， 我认为在敏捷开发里面的自动化测试是有2条路线，并且这2条路是并行的，缺一不可 至少一个自动化回归测试框架，保证release前能够对产品进行覆盖较为全面的回归测试 工作中*不断地*开发自动化测试工具，提高自己的生产率 以上两点的目的很简单，就是要在保持产品质量处于一个较高水平的情况下，帮助公司尽可能地快速交付新版本的产品。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>上周在51testing上看到一个问题，题目是在敏捷开发中，自动化测试应该如何开展呢？当时在论坛上回复了一下，现在放到博客，稍微调整一下。</p>
<p>首先，敏捷开发并不是部分同学想象中的那样，没有文档没有需求，开发来了就干，干几个月就丢给客户一个版本让他们用去。我们公司一般6个星期是一个release周期，在这6个星期里面，可以做的事情是非常多的。</p>
<ul type="1">
<li>需求，需求通常来自于PM，在一个release周期的开始，QA通常没太多事情需要做，比较轻松，这个时候一个比较重要的工作就是跟PM沟通当前release里面的一些feature的情况。在这个时候，QA可以做一些自动化测试的准备。例如在某个release周期里，我知道在接下来的测试当中我需要频繁地比较CSV文件，那么作为QA就应该在项目还不是很紧张的时候，就开始准备自动化测试的脚本，例如刚才说的这个CSV文件比较工作。</li>
<li>开始开发，如果公司是实时TDD开发，那么这个时候QA可以做的事情大概有2个，帮助开发写单元测试用例，并且实施自动化测试（主要是单元测试），另一个是review（虽然不是自动化测试的内容）。如果不是采用TDD开发，那么QA做的事情跟上一个阶段的做的差不多。</li>
<li>正式提交测试，OK，这个时候是我们QA比较忙的时候，有可能出现几个情况，1. 跟我的预想一样，我真的需要一个CSV文件比较工作，并且只需要这一个工具，并且我已经完成了，那么就可以进行测试了。2. 可能有一些新的自动化测试需求跑出来了，例如每天晚上自动比较几万个CSV文件并且把测试结果发给相关的人，这时候作为QA，在考虑资源允许的情况下，应该尽早完成这个工具，而不是每天晚上爬起来看结果。</li>
<li>发布完毕以后，回过头来看工具，是否有值得改进的地方，是否能够改进一下就能够给整个Team使用。</li>
</ul>
<p>以上算是一个release周期里面的一些微观的工作，宏观上来说需要做点什么事情呢？</p>
<p>现在提到的敏捷开发，都有一个很突出的特点，就是产品快速交付给客户，为了快速交付这个目的，公司里面每个团队都作出了努力，那么具体到QA团队，肯定就是要在保持测试质量得到保证的前提下，尽可能地缩减测试所需要的时间，使得产品按时按质交付。要达到这个目的，总靠一些AD-HOC的工作（例如刚才提到的突然写个CSV比较工具）是不可能达到要求的，那应该如何进行呢？</p>
<p>敏捷开发也是开发，产品不是孙悟空，不会某一天就从石头里面爆出来了。在产品开发的前期（例如0.1, 0.2版本之类），尽可能地想办法搭建一个自动化回归测试的框架，这个框架的特点有：1. 快速完成回归测试； 2.能够快速地添加测试用例并且跑起来；3.能够随着产品的演化而不断改进（不能是那种用1~2个release就要扔的东西）；4.维护的成本要低（在一个release周期里面如果自动化测试需求有变化，不应该需要超过1个星期的时间才能改好，当然翻天覆地的变化除外）</p>
<p>综上所述， 我认为在敏捷开发里面的自动化测试是有2条路线，并且这2条路是并行的，缺一不可</p>
<ul type="1">
<li>至少一个自动化回归测试框架，保证release前能够对产品进行覆盖较为全面的回归测试</li>
<li>工作中*不断地*开发自动化测试工具，提高自己的生产率</li>
</ul>
<p>以上两点的目的很简单，就是要在保持产品质量处于一个较高水平的情况下，帮助公司尽可能地快速交付新版本的产品。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/agile-testing/automation-testing-in-agile/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>内部自动化测试交流有感</title>
		<link>http://magustest.com/blog/automationtesting/test-automation-thought/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=test-automation-thought</link>
		<comments>http://magustest.com/blog/automationtesting/test-automation-thought/#comments</comments>
		<pubDate>Sun, 29 Aug 2010 03:55:07 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[敏捷测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=669</guid>
		<description><![CDATA[上周公司组织了一个交流会，主题是关于自动化测试，这个已经在公司引起高层们足够重视的话题，说是交流会，其实我更觉得是个成果展示会，本人代表CORE QA跟大家分享了一下我们组内自动化测试的一些情况，并且在做的过程中的一些经验。我是第一个，下面是VI的自动化测试，VI主要是跟Video播放器结合的比较紧密，最后是UI同事的介绍。我从头到尾都参与，所以说说的我感受吧。 CORE这边测试的特点就是，针对MRM系统的后台进行测试，肩带来说就是模拟各种跟后台打交道的“程序”的工作，进行测试。我们测试有以下特点： 直接跟后台程序交互，基本没有现成的开源或者商业工具可以支持自动化测试快速开展 测试验证结果大多数是后台的输入，也就是前台或者是第三方系统的输入，所以验证的方法不能简单地观察输出结果，同时需要知道后台的输出拿到别的系统能否正常工作 牵涉到数据迁移或者数据重处理的时候，QA需要直接读取生产环境的数据进行校验 由于以上特点，所以我们的自动化测试85%都是自己开发工具来做，常用的脚本语言是Python，经常用到的一些模块包括读取MySQL的MySQLdb；csv模块；re模块；总得原则就是把重复性强，容易引入错误的工作都写成小工具。并且尽可能使用已有的成熟的库，而不是自己重复发明轮子。例如我们的前端页面使用了web.py轻量级框架，JSON库。到目前为止，我自己感觉我们的自动化测试还是做的不错的，主要是以下几点 简单。说起自动化测试，可能有部分人，或者说是外行的人吧，都觉得这个东西非常酷，人只要倒杯咖啡看着电脑执行测试就好了。但是其实实用有效的自动化测试并不是说看起来有多酷，而是这个东西能把人从重复劳动中解放出来。 强大。我刚到公司的时候，已经有600多个回归测试跑在自动化框架上，我当时就觉得已经挺不错的，因为这个自动化测试是由大概4~5个不同的人做的，我以前在MySpace的时候SOA大概有300个CASE，不过那都是我一个人做的，相比较而言FreeWheel应该是更好。 持续改进。虽然我刚到公司的时候自动化测试已经存在并且也算是行之有效，但是任何系统都是有可改进的空间的，我把前端UI改了一下，很高兴可以帮助大家缩短了找问题的时间 全面。基本上所有的模块都有自己的一堆自动化测试工具。 引用一句我非常喜欢的英语：So far so good。那下面我想做什么事情呢？ 自动化测试其实不是测试，只是重复运行测试用例而已。真正的测试用的是脑，而不是工具，工具只是辅助我们的工作的 自动化测试是危险的，不要看到所有回归测试都通过了，就高枕无忧 手动测试才是根本 希望能给大家灌输一些思想，如果发现自己在重复做一件事情，那么应该停下来，想想有什么办法能够让自己停止重复，尽可能自己解决问题，培养自己的动手能力 看看有没有一些开源工作能让现在的工作做的更加好 下面说说对VI TEAM自动化测试介绍的一点感觉吧，VI和CORE有点儿相似，就是都是用的自己开发的自动化工具，而没用应用了太多开源工具，我个人觉得这里面原因有2个 VI的测试面向Video播放器的SDK，也是一个后台，所以也没有太多现成的工具 用户怎么用我们的SDK？就是调用接口，跟CORE面对的问题相似 估计由于经常跟XML打交道，所以VI的自动化测试用到很多XML文件作为配置。由于隔行如隔山，所以没有看懂里面的一些玄机，总的来说就是跟我们CORE有点相似。 我们CORE和VI一样，这些工具如果跳出了这个公司，基本上就不能应用到其他地方，这也是对整个系统来说的底层部分做自动化测试的特点：高度定制化，通用性低，自己开发居多 最后就是UI的介绍，终于等到一个看得懂的啦。 UI那边就是大量使用开源工具，这个也是很有道理的 UI的自动化测试实施难度比后台程序的自动化要大 现有的UI自动化测试非常丰富 那我们的UI是怎么做的呢？首先UI的同事用了一个持续集成的工具hudson作为一个颗粒度比较粗的测试用例管理工具，hudson作为自动化测试的主心骨，QA们可以在hudson上触发自动化测试的运行，运行完了以后可以看到测试结果，并且，利用了hudson的分布式结构，由多个测试机来执行测试，达到了很好的资源调配。对浏览器的控制方面，用了Selenium，会上没有问UI是否利用了Selenium的多浏览器支持，从演示上来看应该只做的Firefox的。他们的分工很明确，分了专门做功能测试的QA和专门做自动化测试工具开发的SDET，SDET主要是负责写RUBY代码，封装并且暴露了一些通用的方法给QA使用，并且同时使用了Cucumber作为一个DSL，QA是用Cucumber来做自动化测试的一些描述，Cucumber的作用就是对功能测试的QA屏蔽了底层RUBY脚本，对上就是“翻译”功能测试QA的意图，“翻译”成RUBY。说一下我觉得的优点： 分开了自动化测试工具开发和自动化测试实施 使用了大量开源工具，提高效率 而且都是业界常用工具，对以后跳槽帮助不小（嘿嘿） One click automation (只需要点一下hudson） 一些工具带来的制约 一次只能运行一批测试，不能重跑单个测试 个人觉得使用XPATH作为对象的识别并不是一个好的选择 总得来说大家都各有特色，并且都做得挺好，并且都有不少可以提高的空间。多点交流的确能带来不少灵感。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>上周公司组织了一个交流会，主题是关于自动化测试，这个已经在公司引起高层们足够重视的话题，说是交流会，其实我更觉得是个成果展示会，本人代表CORE QA跟大家分享了一下我们组内自动化测试的一些情况，并且在做的过程中的一些经验。我是第一个，下面是VI的自动化测试，VI主要是跟Video播放器结合的比较紧密，最后是UI同事的介绍。我从头到尾都参与，所以说说的我感受吧。</p>
<p>CORE这边测试的特点就是，针对<a href="http://www.freewheel.tv/products/mrm/" target="_blank">MRM</a>系统的后台进行测试，肩带来说就是模拟各种跟后台打交道的“程序”的工作，进行测试。我们测试有以下特点：</p>
<ol>
<li>直接跟后台程序交互，基本没有现成的开源或者商业工具可以支持自动化测试快速开展</li>
<li>测试验证结果大多数是后台的输入，也就是前台或者是第三方系统的输入，所以验证的方法不能简单地观察输出结果，同时需要知道后台的输出拿到别的系统能否正常工作</li>
<li>牵涉到数据迁移或者数据重处理的时候，QA需要直接读取生产环境的数据进行校验</li>
</ol>
<p>由于以上特点，所以我们的自动化测试85%都是自己开发工具来做，常用的脚本语言是Python，经常用到的一些模块包括读取MySQL的MySQLdb；csv模块；re模块；总得原则就是把重复性强，容易引入错误的工作都写成小工具。并且尽可能使用已有的成熟的库，而不是自己重复发明轮子。例如我们的前端页面使用了<a href="http://webpy.org/" target="_blank">web.py</a>轻量级框架，JSON库。到目前为止，我自己感觉我们的自动化测试还是做的不错的，主要是以下几点</p>
<ol>
<li>简单。说起自动化测试，可能有部分人，或者说是外行的人吧，都觉得这个东西非常酷，人只要倒杯咖啡看着电脑执行测试就好了。但是其实实用有效的自动化测试并不是说看起来有多酷，而是这个东西能把人从重复劳动中解放出来。</li>
<li>强大。我刚到公司的时候，已经有600多个回归测试跑在自动化框架上，我当时就觉得已经挺不错的，因为这个自动化测试是由大概4~5个不同的人做的，我以前在<a href="http://www.myspace.cn/" target="_blank">MySpace</a>的时候SOA大概有300个CASE，不过那都是我一个人做的，相比较而言<a href="http://www.freewheel.tv/" target="_blank">FreeWheel</a>应该是更好。</li>
<li>持续改进。虽然我刚到公司的时候自动化测试已经存在并且也算是行之有效，但是任何系统都是有可改进的空间的，我把前端UI改了一下，很高兴可以帮助大家缩短了找问题的时间</li>
<li>全面。基本上所有的模块都有自己的一堆自动化测试工具。</li>
</ol>
<p>引用一句我非常喜欢的英语：So far so good。那下面我想做什么事情呢？</p>
<ol>
<li>自动化测试其实不是测试，只是重复运行测试用例而已。真正的测试用的是脑，而不是工具，工具只是辅助我们的工作的</li>
<li>自动化测试是危险的，不要看到所有回归测试都通过了，就高枕无忧</li>
<li>手动测试才是根本</li>
<li>希望能给大家灌输一些思想，如果发现自己在重复做一件事情，那么应该停下来，想想有什么办法能够让自己停止重复，尽可能自己解决问题，培养自己的动手能力</li>
<li>看看有没有一些开源工作能让现在的工作做的更加好</li>
</ol>
<p>下面说说对VI TEAM自动化测试介绍的一点感觉吧，VI和CORE有点儿相似，就是都是用的自己开发的自动化工具，而没用应用了太多开源工具，我个人觉得这里面原因有2个</p>
<ol>
<li>VI的测试面向Video播放器的SDK，也是一个后台，所以也没有太多现成的工具</li>
<li>用户怎么用我们的SDK？就是调用接口，跟CORE面对的问题相似</li>
</ol>
<p>估计由于经常跟XML打交道，所以VI的自动化测试用到很多XML文件作为配置。由于隔行如隔山，所以没有看懂里面的一些玄机，总的来说就是跟我们CORE有点相似。</p>
<p>我们CORE和VI一样，这些工具如果跳出了这个公司，基本上就不能应用到其他地方，这也是对整个系统来说的底层部分做自动化测试的特点：高度定制化，通用性低，自己开发居多</p>
<p>最后就是UI的介绍，终于等到一个看得懂的啦。</p>
<p>UI那边就是大量使用开源工具，这个也是很有道理的</p>
<ol>
<li>UI的自动化测试实施难度比后台程序的自动化要大</li>
<li>现有的UI自动化测试非常丰富</li>
</ol>
<p>那我们的UI是怎么做的呢？首先UI的同事用了一个持续集成的工具<a href="http://hudson-ci.org/" target="_blank">hudson</a>作为一个颗粒度比较粗的测试用例管理工具，hudson作为自动化测试的主心骨，QA们可以在hudson上触发自动化测试的运行，运行完了以后可以看到测试结果，并且，利用了hudson的分布式结构，由多个测试机来执行测试，达到了很好的资源调配。对浏览器的控制方面，用了<a href="http://seleniumhq.org/" target="_blank">Selenium</a>，会上没有问UI是否利用了Selenium的多浏览器支持，从演示上来看应该只做的Firefox的。他们的分工很明确，分了专门做功能测试的QA和专门做自动化测试工具开发的SDET，SDET主要是负责写<a href="http://www.ruby-lang.org/en/" target="_blank">RUBY</a>代码，封装并且暴露了一些通用的方法给QA使用，并且同时使用了Cucumber作为一个DSL，QA是用<a href="http://cukes.info/" target="_blank">Cucumber</a>来做自动化测试的一些描述，Cucumber的作用就是对功能测试的QA屏蔽了底层RUBY脚本，对上就是“翻译”功能测试QA的意图，“翻译”成RUBY。说一下我觉得的优点：</p>
<ol>
<li>分开了自动化测试工具开发和自动化测试实施</li>
<li>使用了大量开源工具，提高效率</li>
<li>而且都是业界常用工具，对以后跳槽帮助不小（嘿嘿）</li>
<li>One click automation (只需要点一下hudson）</li>
</ol>
<p>一些工具带来的制约</p>
<ol>
<li>一次只能运行一批测试，不能重跑单个测试</li>
<li>个人觉得使用<a href="http://www.w3.org/TR/xpath/" target="_blank">XPATH</a>作为对象的识别并不是一个好的选择</li>
</ol>
<p>总得来说大家都各有特色，并且都做得挺好，并且都有不少可以提高的空间。多点交流的确能带来不少灵感。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/test-automation-thought/feed/</wfw:commentRss>
		<slash:comments>4</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>自动化测试中的sleep</title>
		<link>http://magustest.com/blog/automationtesting/sleep-in-test-automation/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sleep-in-test-automation</link>
		<comments>http://magustest.com/blog/automationtesting/sleep-in-test-automation/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 13:44:40 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[自动化测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=647</guid>
		<description><![CDATA[最近在修改公司现有的一个自动化测试框架，里面用了很多time.sleep()方法，看着不是很爽，为什么我觉得sleep方法在自动化测试中不应该过多的使用呢，我甚至觉得应该尽可能避免sleep方法的使用，sleep可以作为增加自动化测试稳定性的手段，但是不能依赖sleep来让自动化系统稳定。 举个例子，如果一个UI的自动化测试，需要等待某个页面load完成以后才进行操作，那么需要对那个页面是否已经Load完成进行判断，而不应该sleep(x)，x是一个magic number，有时候1、2秒就足以，有时候它却不知道有多大，因为已经超时了！那如果我们在check页面状态之前做一个短时间的sleep，那么在某些场合下可以增加这个自动化测试的稳定性，但是最终整个自动化测试的脚本是不会依赖于这个sleep的语句来达到稳定的。 在做自动化测试的时候，最常见的两种判断就是1. 某程序已经成功启动，某页面已经加载完毕。 2. 某程序已经正常关闭，某服务已经顺利停止。 回到实际的工作，我要判断被测的程序是否已经正常启动，可以用系统提供的一些工具，或者调用一些接口，例如SNMP命令，或者是调用一下Lua脚本等，如果他们都返回我们期望的数据，那么可以认为程序已经成功启动了。反之，如果前面的这些命令出错了，那么我也可以认为程序已经是关闭了的。 要实现自动化测试，就必须要让测试代码每时每刻都掌握着被测系统的状态，sleep方法会让自动化测试脚本的行为变得诡异。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>最近在修改公司现有的一个自动化测试框架，里面用了很多time.sleep()方法，看着不是很爽，为什么我觉得sleep方法在自动化测试中不应该过多的使用呢，我甚至觉得应该尽可能避免sleep方法的使用，sleep可以作为增加自动化测试稳定性的手段，但是不能依赖sleep来让自动化系统稳定。</p>
<p>举个例子，如果一个UI的自动化测试，需要等待某个页面load完成以后才进行操作，那么需要对那个页面是否已经Load完成进行判断，而不应该sleep(x)，x是一个magic number，有时候1、2秒就足以，有时候它却不知道有多大，因为已经超时了！那如果我们在check页面状态之前做一个短时间的sleep，那么在某些场合下可以增加这个自动化测试的稳定性，但是最终整个自动化测试的脚本是不会依赖于这个sleep的语句来达到稳定的。</p>
<p>在做自动化测试的时候，最常见的两种判断就是1. 某程序已经成功启动，某页面已经加载完毕。 2. 某程序已经正常关闭，某服务已经顺利停止。</p>
<p>回到实际的工作，我要判断被测的程序是否已经正常启动，可以用系统提供的一些工具，或者调用一些接口，例如SNMP命令，或者是调用一下Lua脚本等，如果他们都返回我们期望的数据，那么可以认为程序已经成功启动了。反之，如果前面的这些命令出错了，那么我也可以认为程序已经是关闭了的。</p>
<p>要实现自动化测试，就必须要让测试代码每时每刻都掌握着被测系统的状态，sleep方法会让<a href="http://magustest.com/blog/automationtesting/avoid-flakey-automation-test/" target="_blank">自动化测试脚本的行为变得诡异</a>。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/sleep-in-test-automation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

