1. 程式人生 > >【selenium】利用excel來實現關鍵字驅動-Java

【selenium】利用excel來實現關鍵字驅動-Java

參考地址:https://my.oschina.net/hellotest/blog/531932#comment-list

一、新建專案


二、匯入包


三、例子-excel

    以CSDN的登入為例,首先我們可以分解登入的步驟,寫入excel,如下:



四、編碼

1、首先需要寫一個可以讀寫excel的方法,我電腦上裝的是excel7,xlsx格式,用到XSS系列的方法,程式碼如下:

package com.model.lib;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 *  操作excel類
 * @author Admin
 *
 */
public class ExcelUtil {
	
	public static XSSFSheet excelSheet;
	public static XSSFWorkbook excelBook;
	public static XSSFRow row;
	public static XSSFCell cell;
	
	/**
	 *  載入excel
	 * @param path excel檔案路徑
	 */
	public static void setExcelFile(String path) {
		FileInputStream excelFile;
		
		try {
			excelFile = new FileInputStream(path);
			excelBook = new XSSFWorkbook(excelFile);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 獲取excel中對應單元格的值
	 * @param rownum 行(從0開始)
	 * @param cellnum 列(從0開始)
	 * @param sheetName sheet名
	 * @return
	 */
	public static String getCellData(int rownum,int cellnum,String sheetName) {
		excelSheet = excelBook.getSheet(sheetName);
		cell = excelSheet.getRow(rownum).getCell(cellnum);
		String cellData = cell.getStringCellValue();
		return cellData;
	}
	
	/**
	 *  將測試結果寫入excel
	 * @param result 測試結果
	 * @param rownum 行(從0開始)
	 * @param cellnum 列(從0開始)
	 * @param path excel檔案路徑
	 * @param sheetName sheet名
	 */
	public static void setCellData(String result,int rownum,int cellnum,String path,String sheetName) {
		try {
			excelSheet = excelBook.getSheet(sheetName);
			row = excelSheet.getRow(rownum);
			cell = row.getCell(cellnum, row.RETURN_BLANK_AS_NULL);
			if (cell == null) {
				cell = row.createCell(cellnum);
				cell.setCellValue(result);
			} else {
				cell.setCellValue(result);
			}
			FileOutputStream fileOut = new FileOutputStream(path);
			excelBook.write(fileOut);
			fileOut.flush();
			fileOut.close();
			excelBook = new XSSFWorkbook(new FileInputStream(path));
		}catch (Exception ex) {
			ex.printStackTrace();
		}
		
	}
	
	/**
	 * 獲取excel的sheet的最後一行
	 * @param sheetName
	 * @return
	 */
	public static int getLastRownum(String sheetName) {
		int row = 0;
		try {
			excelSheet = excelBook.getSheet(sheetName);
			row = excelSheet.getLastRowNum();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return row;
	}
	

}

2、登入步驟需要用到的方法,對應login的測試步驟

package com.model.keyword;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

import com.model.lib.DataStore;

/**
 *   關鍵字步驟對應的方法
 * @author Admin
 *
 */
public class LoginKeyword {
	
	public static WebDriver driver;
	
	/**
	 *  開啟瀏覽器並最大化視窗
	 */
	public static void OpenBrowser() {
		System.setProperty(DataStore.key, DataStore.driverurl);
		if (DataStore.startExplore.equals("firefox")) {
			driver = new FirefoxDriver();
		} else if (DataStore.startExplore.equals("chorme")){
			driver = new ChromeDriver();
		} else {
			driver = new InternetExplorerDriver();
		}
		
		driver.manage().window().maximize();
	}
	
	/**
	 *  開啟網址
	 */
	public static void Navigate() {
		driver.get(DataStore.loginUrl);
	}
	
	/**
	 *  輸入使用者名稱
	 * @param pe 頁面元素
	 * @param value 輸入的值
	 */
	public static void InputUsername(String pe,String value) {
		driver.findElement(By.id(pe)).clear();
		driver.findElement(By.id(pe)).sendKeys(value);
	}

	/**
	 *  輸入密碼
	 * @param pe 頁面元素
	 * @param value 輸入的值
	 */
	public static void InputPassword(String pe,String value) {
		driver.findElement(By.id(pe)).clear();
		driver.findElement(By.id(pe)).sendKeys(value);
	}
	
	/**
	 *  點選登入
	 * @param pe 頁面元素
	 */
	public static void ClickLogin(String pe) {
		driver.findElement(By.xpath(pe)).click();
	}
	
	/**
	 *  關閉瀏覽器
	 */
	public static void CloseBrowser() {
		driver.quit();
	}

}
3、根據excel將需要的引數定義出來(Config.properties)
# 瀏覽器驅動路徑
startExplore = firefox
key = webdriver.firefox.bin
driverurl = C:/Program Files/Mozilla Firefox/firefox.exe

4、讀取引數檔案

package com.model.lib;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

/**
 *  讀取配置檔案的內容
 * @author Admin
 *
 */
public class PropertiesFile {

	public static String read(String key) {
		Properties pps = new Properties();
		InputStream in = null;
		try {
			// 讀取config檔案
			File file = new File("F:/selenium/workplace/CsdnKeywordModel/assets/Config.properties");
			in = new BufferedInputStream(new FileInputStream(file));
			pps.load(in);// 載入屬性列表
			
			if (pps.containsKey(key)) {
				String value = pps.getProperty(key);
				return value; // 返回讀取的內容
			} else {
				System.out.println("沒有讀取到"+key);
				return null;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}	
	}
	
	public static void main(String[] args) {
		PropertiesFile pf = new PropertiesFile();
		String ss = pf.read("user");
		System.out.println(ss);
	}
}

5、讀取的資料

package com.model.lib;


/**
 *  讀取的資料
 * @author Admin
 *
 */
public class DataStore {
	
	    // 驅動路徑
		public static String driverurl = PropertiesFile.read("driverurl");
		public static String key = PropertiesFile.read("key");
		
		public static String startExplore = PropertiesFile.read("startExplore");

	public static void main(String[] args) {
		System.out.println(driverurl);
	}
}

6、定義登入時需要用到的常量

package com.model.keyword.contant;

/**
 *  登入關鍵字需要的常量
 * @author Admin
 *
 */
public class LoginContant {
	
	// 登入URL
	public static String loginUrl = "https://passport.csdn.net/account/login";
	
	// 讀取檔案的資料夾路徑
	public static String TextPath = "F:/selenium/workplace/CsdnKeywordModel/assets/";
	
	// 讀取的檔名
	public static String fileName = "pageElements.xlsx";
	
	// 讀取的檔案的sheet
	public static String suiteSheet = "Suite";
	public static String caseSheet = "login";
	
	// 用例執行的結果定義
	public static String pass = "PASS";
	public static String fail = "FAIL";
	
	//suite需要用到的引數(對應值所在的列)
	public static int suiteTestIdCol = 0;
	public static int suiteRunmodeCol = 2;
	public static int suiteResultCol = 3;
	
	// case需要用到的引數(對應值所在的列)
	public static int caseTestIdCol = 0;
	public static int caseKeywordCol = 1;
	public static int casePageElementCol = 3;
	public static int casePageValueCol = 4;
	public static int caseResultCol = 5;

}
7、利用反射執行關鍵字類中的方法(這裡注意,如果excel表格中沒有值的話,不能為空,要寫“無”)
package com.model.lib;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.model.keyword.contant.LoginContant;

/**
 *  將excel的處理邏輯和關鍵字邏輯相分離
 * @author Admin
 *
 */
public class CommonEngine {
	
	/**
	 *  執行關鍵字中的方法
	 * @param keyword 關鍵字方法名稱
	 * @param actionKeywords 關鍵字類
	 * @param pe 頁面元素
	 * @param value 需要用到的值
	 * @param rownum 哪一行
	 * @param sresult 執行結果
	 */
	public static void Action(String keyword,Object actionKeywords,String pe,String value,int rownum,boolean sresult) {
		// 根據反射機制獲取關鍵字類中的方法
		Method[] method = actionKeywords.getClass().getMethods();
		for (int i = 0; i < method.length; i++) {// 迴圈遍歷關鍵字類中的方法
			if (method[i].getName().trim().equals(keyword)) { // 如果關鍵字類中的方法和excel關鍵字的方法一致
				try {
					if (pe.equals("無") && value.equals("無")) {
						method[i].invoke(actionKeywords);
					} else if (!(pe.equals("無")) && value.equals("無")) {
						method[i].invoke(actionKeywords, pe);
					} else if (pe.equals("無") && !(value.equals("無"))) {
						method[i].invoke(actionKeywords, value);
					} else {
						method[i].invoke(actionKeywords, pe, value);
					}
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
				break;
			}
		}
	}

}
8、編寫登入的指令碼
package com.model.test;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.junit.Test;

import com.model.keyword.LoginKeyword;
import com.model.keyword.contant.LoginContant;
import com.model.lib.CommonEngine;
import com.model.lib.ExcelUtil;

public class Login {
    public static Logger logger = Logger.getLogger(Login.class.getName());
	public static LoginKeyword loginkeyword;
	public static String keyword;
	public static String pe;
	public static String value;
	public static boolean result;
	
	public Login () {
		loginkeyword = new LoginKeyword();
	}
	
	@Test
	public void test() {
		ExcelUtil.setExcelFile(LoginContant.TextPath+LoginContant.fileName);// 載入登入檔案
		new Login();
		result = true;
		//迴圈讀取suitSheet裡面的值,找出執行的場景
		for (int j = 1;j<=ExcelUtil.getLastRownum(LoginContant.suiteSheet);j++) {			
			// 讀取suitesheet裡面的runmode欄位,如果為yes則執行該用例,No則不執行
			String runMode = ExcelUtil.getCellData(j, LoginContant.suiteRunmodeCol, LoginContant.suiteSheet);
			// 讀取suitesheet裡面的testsuiteID欄位
			String suiteTestid = ExcelUtil.getCellData(j, LoginContant.suiteTestIdCol, LoginContant.suiteSheet);
			//int srownum;
			if (runMode.equals("YES")) {
				logger.log(Level.INFO, "開始執行第"+j+"條");
				// 迴圈遍歷loginsheet裡面的值,找出執行的步驟
				for (int srownum = 1;srownum<=ExcelUtil.getLastRownum(LoginContant.caseSheet);srownum++) {
					// 獲取loginsheet裡面的測試用例序號
					String loginTestid = ExcelUtil.getCellData(srownum, LoginContant.caseTestIdCol, LoginContant.caseSheet);
					if (loginTestid.trim().equals(suiteTestid)) { // 如果loginsheet裡面的測試用例序號和suitesheet裡面的用例序號一致
						// 獲取loginsheet裡面的測試步驟序號(和loginkeyword裡面的方法對應)
						keyword = ExcelUtil.getCellData(srownum, LoginContant.caseKeywordCol, LoginContant.caseSheet);
						// 獲取loginsheet裡面的頁面元素(id,xpath路徑等)
						pe = ExcelUtil.getCellData(srownum, LoginContant.casePageElementCol, LoginContant.caseSheet);
						// 獲取loginsheet裡面的值(需要輸入或者對比的值)
						value = ExcelUtil.getCellData(srownum, LoginContant.casePageValueCol, LoginContant.caseSheet);
						CommonEngine.Action(keyword, loginkeyword, pe, value, srownum, result);
						if (result == true) {// 將結果寫入loginsheet
							ExcelUtil.setCellData(LoginContant.pass, srownum, LoginContant.caseResultCol, LoginContant.TextPath+LoginContant.fileName, LoginContant.caseSheet);
						} else {// 將結果寫入loginsheet
							ExcelUtil.setCellData(LoginContant.fail, srownum, LoginContant.caseResultCol, LoginContant.TextPath+LoginContant.fileName, LoginContant.caseSheet);
						}
						if (result == false) {// 將結果寫入suitesheet
							ExcelUtil.setCellData(LoginContant.fail, j, LoginContant.suiteResultCol, LoginContant.TextPath+LoginContant.fileName, LoginContant.suiteSheet);
							logger.log(Level.INFO, "第"+j+"條用例執行完成");
						}
					}
				}
				if (result == true) {// 將結果寫入suitesheet
					ExcelUtil.setCellData(LoginContant.pass, j, LoginContant.suiteResultCol, LoginContant.TextPath+LoginContant.fileName, LoginContant.suiteSheet);
					logger.log(Level.INFO, "第"+j+"條用例執行完成");
				}
			} else {
				logger.log(Level.INFO, "沒有要執行的用例");
				break;
			}
		}
	}
}

9、在套件中執行

package com.model.mysuite;

import com.model.report.HtmlReport;
import com.model.test.Login;

import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

public class MySutieMain {
	
	public static Test suite() { 
			TestSuite suite = new TestSuite();
			suite.addTest(new JUnit4TestAdapter(Login.class));	//登入
			//suite.addTest(new JUnit4TestAdapter(HomePageAutoTest.class));		//首頁
	        return suite;  
	} 
	
	
	
	public static void main(String args[]) { 
		HtmlReport hr=new HtmlReport();
		hr.createLog("F:\\selenium\\report\\jdhuiTestlog.html");
		TestRunner.run(suite()); 
		hr.closeLog();
	}
}