初识Concordion与入门

问题域?

测试及文档,Specification By Example 应该怎么做,怎样提高测试的效率。

什么是Concordion ?

Concordion是一种自动化测试框架,是测试及文档,Specification By Example的一种实现,可以用自然的语言来描述软件功能,能很好的描述用户的Story。它不仅支持Java,也同样支持.NET, Python, Scala, and Ruby. 是JUnit的扩展,写好的测试不仅是格式良好的测试文档,同样也可以当成JUnit单元测试来跑。

如何使用 ?

Concordiong很简单,我们可以直接看看官方的例子。

1. 安装

下载例子concordion-kickstart, 例子使用Gradle构建工具管理的,比maven简单,这里就不详细介绍它的使用方式了。


 Greeter.java 需要测试的类。

 specs 验收测试归类文件夹。

 concordion.css 级联样式表让测试展现更好看一点。

 HelloWordTest.java JUnit测试类,集成至ConcordionTestCase

 HelloWord.html Concordion测试文档,名字必须与测试类保持一致。

环境要求Jdk1.5以上,依赖一下jar包:

  • concordion-1.4.2.jar
  • junit-3.8.2.jar or junit-4.8.2.jar
  • ognl-2.6.9.jar
  • xom-1.2.5.jar

2. 导入项目到IDE中,Eclipse或者IntelliJ IDEA

使用Gradle很方便导入,在gradle的构建脚本build.gradle最前面加上或者intellij插件即可,如下:

然后在命令行运行 gradle eclipse或者gradle idea,然后通过IDE导入就可以了。

3. Concordion测试

Concordion测试文档需要遵循一些固定的格式,它必须是一个格式良好的XHTML文档,所以必须包含 

<html xmlns:concordion="http://www.concordion.org/2007/concordion">

concordion:assertEquals用来断言结果的正确性。

concordion:set设置变量值。

concordion:execute执行测试类方法。

看第一个简单的例子:

JUnit测试类:

 

package com.example.specs.greeting;

import org.concordion.integration.junit3.ConcordionTestCase;

import com.example.Greeter;

public class HelloWorldTest extends ConcordionTestCase {
    
    public String greetingFor(String firstName) {
        return new Greeter().greetingFor(firstName);
    }

	public void setCurrentTime(String time) {
		// TODO
	}
}

测试文档:

<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<link href="../concordion.css" rel="stylesheet" type="text/css" />
<body>

    <h1>Hello World!</h1>

    <p>
    	After a user logs into the system, a greeting is
    	displayed saying "Hello [user's first name]!"
    </p>

    <div class="example">

		<h3>Example</h3>
		
        <p>
            When user <b concordion:set="#firstName">World</b>
            logs in, the greeting will be:
            <b concordion:assertEquals="greetingFor(#firstName)">Hello World!</b>
        </p>

		<p>
			If time is
			<span concordion:execute="setCurrentTime(#TEXT)">09:00AM</span>
		</p>

    </div>

</body>
</html>


第一个测试很容易理解greetingFor函数接受一个字符串并返回,通过concordion:set设置firstName为World,用concordion:assertEquals判断最后结果是否是Hello World.输出界面为:


第二个例子:测试函数返回值

package com.example.specs.greeting;

import org.concordion.integration.junit3.ConcordionTestCase;

public class SplittingNamesTest extends ConcordionTestCase{

	public Result split(String fullName){
		String[] words = fullName.split(" ");
		Result result = new Result(words[0], words[1]);
		return result;
	}

	class  Result  {
		private final String firstName;
		private final String lastName;

		Result(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		public String getFirstName(){
			return firstName;
		}

		public String getLastName(){
			return lastName;
		}
	}
}

<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<head>
	<link href="../concordion.css" rel="stylesheet" type="text/css"/>
</head>
<body>
    <h1>Splitting Names</h1>

	<p>
		To help personalise our mailshots we want to have the first name
		and last name of the customer. Unfortunately the customer data
		that we are supplied only contains full names.
	</p>

	<p>
		The system therefore attempts to break a supplied full name into
		its constituents by splitting around whitespace.
	</p>

	<div class="example">
		<h3>Example</h3>

		<table>
			<tr>
				<th>Full Name</th>
				<th>First Name</th>
				<th>Last Name</th>
			</tr>
			<tr concordion:execute="#result=split(#fullName)">
				<td concordion:set="#fullName">John Smith</td>
				<td concordion:assertEquals="#result.firstName">John</td>
				<td concordion:assertEquals="#result.lastName">Smith</td>
			</tr>
			<tr concordion:execute="#result=split(#fullName)">
				<td concordion:set="#fullName">David Peterson</td>
				<td concordion:assertEquals="#result.firstName">David</td>
				<td concordion:assertEquals="#result.lastName">Peterson</td>
			</tr>
		</table>
	</div>
</body>
</html>

使用concordion:execute调用函数split,返回结果保存在result变量里面,Concordion会自动把它映射为Result对象。

第三个例子:测试数据集

package com.example.specs.greeting;

import org.concordion.integration.junit3.ConcordionTestCase;

import java.util.*;

public class PartialMatchesTest extends ConcordionTestCase {

	private Set<String> usernamesInSystem  = new HashSet<String>();

	public void setUpUser(String username){
		usernamesInSystem.add(username);
	}

	public Iterable<String> getSearchResultsFor(String searchString){
		SortedSet<String> matches = new TreeSet<String>();
		for(String username : usernamesInSystem){
			if(username.contains(searchString)){
				matches.add(username);
			}
		}
		return matches;
	}
}

<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<head>
	<link href="../concordion.css" rel="stylesheet" type="text/css"/>
</head>
<body>
	<h1>Partial Matches</h1>
	<p>
		Username searches return partial matches, i.e. all usernames containing
		the search string are returned.
	</p>

	<div class="example">
		<h3>Example</h3>
		<p>Given these users:</p>

		<table concordion:execute="setUpUser(#username)">
			<tr><th concordion:set="#username">Username</th></tr>
			<tr><td>john.lennon</td></tr>
			<tr><td>ringo.starr</td></tr>
			<tr><td>george.harrison</td></tr>
			<tr><td>paul.mccartney</td></tr>
		</table>

		<p>Searching for "<b concordion:set="#searchString">arr</b>" will return:</p>

		<table concordion:verifyRows="#username:getSearchResultsFor(#searchString)">
			<tr><th concordion:assertEquals="#username">Matching Usernames</th></tr>
			<tr><td>george.harrison</td></tr>
			<tr><td>ringo.starr</td></tr>
		</table>
	</div>
</body>
</html>

使用concordion:verifyRows来接受结果集,并判断结果集中的数据,相当简单一看就懂。

结束语

通过上面的例子看Concordion还是比较简单的,它鼓励把测试写成类似用户Story描述那样,让项目中的每个人都能看懂测的具体是什么场景包括BA或者其他不懂技术的人。它是JUnit的扩展,能像JUnit测试一样自动话执行和生成结果。比起其他的BDD工具JBehave, Cucumber有些区别的就是它并不使用Given When Then的格式,它提倡自然语言Specification By Example的方式来描述测试用例。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值