`

一个简单的Web UI自动化测试框架Java实现

阅读更多

简介

原创文章,转载请注明出处

这个框架的名字叫OAT,全称Object-Oriented  Automation Test.这个框架的思想借助于Tellurium框架.他的主要功能是将页面信息及行为存储在Java 对象中,然后在脚本中引用页面的行为.自动化程序最终由许多的页面行为组成.这个框架默认使用Selenium1驱动,并且可以通过编程使用其他驱动,因为OAT是面向接口的.

 

以下以google home page的demo为例,介绍这个基于Annoation和反射的框架基本运行原理.

 

page对象

 

//存储页面URL
@OatPage("webhp") 
public class GooglePage extends Page{
	@Element("q") // 搜索输入框的定位符
	private TextField textField;
	@Element("btnG") // 搜索按钮的定位符
	private Button searchButton;
	
	// TextField和Button有共同的祖先类Element
	public TextField getTextField() {
		return textField;
	}
	public Button getSearchButton() {
		return searchButton;
	}
	//进行一次搜索
	public void doSearch(String q){
		this.textField.type(q);
		this.searchButton.click();
	}	

}

 TextField和button类

 

// Element子类,有自己独特的行为
public class TextField extends Element {
	
	public void type(String value) {
		vendor.type(locator, value);
	}
	
	public boolean idEditable(){
		return vendor.isEditable(locator);		
	}
	
	public String getValue() {
		return vendor.getAttribute(locator);
	}

}
// 同样是Element的子类,有自己行为
public class Button extends Element {
	
	
	public void click() {
		vendor.click(locator);
	}
	
	public void clickAndWaitToLoad(Page page){
		click();
		page.waitToLoad();
	}
	
	public void clickAndWaitToLoad(Page page, long timeout) {
		click();
		page.waitToLoad(timeout);
	}
	
	public void clickAndWaitToLoad(Element element, long timeout) {
		click();
		element.waitToLoad(timeout);
	}
	
	public void clickAndWaitToLoad(Element element) {
		clickAndWaitToLoad(element, ELEMENT_DEFAULT_TIMEOUT);
	}
	
}
 

 

自动化测试脚本代码

 

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class GoogleSearchTestExample1 {
	
	private String serverUrl = "localhost";
	private int serverPort = 4444;
	private String browserCommand = "googlechrome";
	private String url = "http://www.google.com.hk";
	
	private GooglePage page;
	private GoogleResultPage resultPage;
	private Selenium selenium;
	private Oat oat;

	@Before
	public void setUp() throws Exception {
		// 初始化selenium
		selenium = new DefaultSelenium(serverUrl,serverPort,browserCommand, url);
		// Oat类是框架总的控制器,设置Selenium为背后的驱动
		oat = Oat.getInstance(selenium);
		oat.start();
		oat.open("/webhp");
		// 初始化被测试页面
		page = (GooglePage) oat.getPage(GooglePage.class);
		resultPage = (GoogleResultPage) oat.getPage(GoogleResultPage.class);

	}
	
	@Test
	public void testSearch() throws InterruptedException {
		// 在google页面收入"oat"进行搜索
                page.doSearch("oat");		
		page.waitToLoad(2000);
		// 在结构页面进行验证
		boolean result = resultPage.isTextPresent("oat");
		Assert.assertTrue("Text oat is present", result);
	}

	@After
	public void tearDown() throws Exception {
		oat.stop();
		oat = null;
		page = null;
		selenium = null;
	}

}

 

Oat.getInstance(Object engine):用于获取真正的Driver:

//可以根据传入的不同engine,实例化不同的Vendor
public static Oat getInstance(Object engine) {
		if(instance == null) {
			synchronized(Oat.class) {
				if(instance == null) {
					
					String vendorTypeStr = getVendorTypeStr();
					
					try {
						Class<?> vendorType = Class.forName(vendorTypeStr);
						Vendor vendor = getVendor(vendorType, engine);				
						instance = new Oat();
						instance.vendor = vendor;
						
					} catch (ClassNotFoundException e) {
						throw new RuntimeException("Not Found vendor " + vendorTypeStr, e);
					} 
				}
			}
		}
		
		return instance;
	}

 

Oat.getPage()方法详解

public Page getPage(Class<? extends Page> pageType) {
		Page page = null;
		
		page = initialize(pageType);
		page.setVendor(vendor);
		
	}

private Page initialize(Class<? extends Page> pageType) {
                //读取page类中的annotation
		OatPage anno = pageType.getAnnotation(OatPage.class);
		
		if(anno == null) {
			throw new RuntimeException("Please add com.perficient.oat.component.annotaion.OatPage annotation in Page class!");
		}
		
		Page page = null;
		try {
			page = pageType.newInstance();
		} catch (Exception e) {
			throw new RuntimeException("Page Class must have a non-parameter constructor.", e);
		} 
		
		Class<?> tempType = pageType;
		
		while(tempType != null) {
			Field[] fields = tempType.getDeclaredFields();
			
			for(Field field : fields ) {
				
				com.perficient.oat.component.annotaion.Element annotation = 
					field.getAnnotation(com.perficient.oat.component.annotaion.Element.class);
				
				if(annotation == null) {
					continue;
				}
				
				Class<?> fieldClazz = field.getType();
				// 只处理Element的子类
				Class<? extends Element> elementClazz = fieldClazz.asSubclass(Element.class);
				
				String locator = annotation.value();
				
				field.setAccessible(true);
                                //使用反射初始化Page类的各个Element子类,并赋予Locator值
				
				try {
					field.set(page, getElement(elementClazz, locator));
				} catch (Exception e) {
					throw new RuntimeException("set Element " + field.getName() + " error", e);
				}
			}
			
			tempType = tempType.getSuperclass();
		}
		
		return page;
		
	}
//用于初始化Page类中的各个Element子类
private Element getElement(Class<? extends Element> elementType, String locator) {
		Element element = null;
		try {
			element = elementType.newInstance();
			element.setLocator(locator);
			element.setVendor(vendor);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 
		return element;
	}

 

 

 

以上就是一个完整的基于Selenium driver的框架实现.以下是我们的Vendor接口:

public interface Vendor {
	
	public void start();
	public void stop();
	public void open(String url);
	public void openWindow(String url, String windowId);
	public void type(String locator, String value);
	public void check(String locator);
	public void uncheck(String locator);
	public boolean isChecked(String locator);
	public boolean isEditable(String locator);
	public void select(String selectLocator, String optionLocator);
	public String getSelectedLabel(String locator);
	public String[] getSelectedLabels(String locator);
	public boolean isSelected(String label);
	public void submit(String formLocator);
	public void click(String locator);
	public boolean isTextPresent(String pattern);
	public boolean isElementPresent(String locator);
	public void waitForPageToLoad(String timeout);
	public void windowFocus(String windowId);
	public String getAttribute(String attributeLocator);
	public String getTableCellValue(String locator, int row, int col);
	public void waitForElementToLoad(String locator, String timeout);
	public String getLocation();
}

 以下是seleniumVendor的实现:

public class SeleniumVendor extends VendorTemplate<Selenium> {

	@Override
	protected Selenium createEngine(VendorAttribute attribute) {
		return new DefaultSelenium(
				attribute.getHost(), 
				attribute.getPort(),
				attribute.getBrowser(),
				attribute.getUrl());
	}
	
	@Override
	public boolean isTextPresent(String pattern) {
		return engine.isTextPresent(pattern);
	}

	@Override
	public void open(String url) {
		engine.open(url);
		
	}

	@Override
	public void select(String selectLocator, String optionLocator) {
		engine.select(selectLocator, optionLocator);
	}

	@Override
	public void start() {
		engine.start();
	}

	@Override
	public void stop() {
		engine.stop();
	}

	@Override
	public void submit(String formLocator) {
		engine.submit(formLocator);
		
	}

	@Override
	public void type(String locator, String value) {
		engine.type(locator, value);
	}

	@Override
	public void click(String locator) {
		engine.click(locator);
		
	}

	@Override
	public void waitForPageToLoad(String timeout) {
		engine.waitForPageToLoad(timeout);
		
	}

	@Override
	public void windowFocus(String windowId) {
		engine.selectWindow(windowId);
		engine.windowFocus();
	}

	@Override
	public void openWindow(String url, String windowId) {
		engine.openWindow(url, windowId);
	}

	@Override
	public void check(String locator) {
		engine.check(locator);
		
	}

	@Override
	public String getAttribute(String attributeLocator) {
		return engine.getAttribute(attributeLocator);
	}

	@Override
	public boolean isElementPresent(String locator) {
		return engine.isElementPresent(locator);
	}

	@Override
	public void uncheck(String locator) {
		engine.uncheck(locator);
		
	}

	@Override
	public boolean isChecked(String locator) {
		return engine.isChecked(locator);
	}

	@Override
	public String getSelectedLabel(String locator) {
		return engine.getSelectedLabel(locator);
	}

	@Override
	public String[] getSelectedLabels(String locator) {
		return engine.getSelectedLabels(locator);
	}

	@Override
	public boolean isSelected(String label) {
		return engine.isSomethingSelected(label);
	}

	@Override
	public boolean isEditable(String locator) {
		return engine.isEditable(locator);
	}

	@Override
	public String getTableCellValue(String locator, int row, int col) {
		return engine.getTable(locator + "." + String.valueOf(row)+ "." +String.valueOf(col));
	}

	@Override
	public void waitForElementToLoad(String locator, String timeout) {
		String script = "selenium.isElementPresent(\"" + locator + "\")";
		engine.waitForCondition(script, timeout);
	}

	@Override
	public String getLocation() {
		return engine.getLocation();
	}


}

 

如果我们需要改成其他Dirver,新建立一个Vendor的实现类即可

1
1
分享到:
评论
2 楼 lijingshou 2014-01-28  
fengbin2005 写道
介绍很详细,谢谢!

欢迎光临
1 楼 fengbin2005 2014-01-28  
介绍很详细,谢谢!

相关推荐

Global site tag (gtag.js) - Google Analytics