前言
Excel编写测试用例能够很快的编写,但是不是很好维护,而Testlink则是编写用例较慢,但是由于是图像界面能够很好的进行用例维护及后期的自动化测试,而testlink支持导入xml文档,于是小编觉得如果把Excel转成xml导入岂不美哉!然鹅在网上找了好久都没有关于使用java 把Excel测试用例转testlink xml较好的例子,要么就是不能满足工作的需求,要么就是不知其所云,在此小编花了点时间结合自己工作中用的模板使用java实现的方式来。OK,咱们开始~
准备条件
首先我们需要知道testlink导出的xml的结构,然后根据xml结构把Excel中的数据解析出来生成符合testlink xml结构的xml文档即可,当然testlink导出的xml文档包含很多信息,我们需要剔除对我们无关紧要的数据,提取其必需的数据,我们来看一下testlink导出xml的原始数据结构:
<?xml version="1.0" encoding="UTF-8"?>
<testsuite id="4564" name="TEST Excel2XML" >
<node_order><![CDATA[0]]></node_order>
<details><![CDATA[]]></details>
<testsuite id="4593" name="testsuite1" >
<node_order><![CDATA[0]]></node_order>
<details><![CDATA[]]></details>
<testsuite id="4594" name="testsuite2" >
<node_order><![CDATA[0]]></node_order>
<details><![CDATA[]]></details>
<testsuite id="4595" name="testsuite3" >
<node_order><![CDATA[0]]></node_order>
<details><![CDATA[]]></details>
<testcase internalid="4596" name="testcase in deep folder">
<node_order><![CDATA[0]]></node_order>
<externalid><![CDATA[1080]]></externalid>
<version><![CDATA[1]]></version>
<summary><![CDATA[<p>description<p/>]]></summary>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<execution_type><![CDATA[1]]></execution_type>
<importance><![CDATA[0]]></importance>
<estimated_exec_duration></estimated_exec_duration>
<status>1</status>
<is_open>1</is_open>
<active>1</active>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
</steps>
</testcase>
<testcase internalid="4627" name="testcase with more than one step">
<node_order><![CDATA[0]]></node_order>
<externalid><![CDATA[1090]]></externalid>
<version><![CDATA[1]]></version>
<summary><![CDATA[<p>description<p/>]]></summary>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<execution_type><![CDATA[1]]></execution_type>
<importance><![CDATA[0]]></importance>
<estimated_exec_duration></estimated_exec_duration>
<status>1</status>
<is_open>1</is_open>
<active>1</active>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
<step>
<step_number><![CDATA[2]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
<step>
<step_number><![CDATA[3]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
<step>
<step_number><![CDATA[4]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
<step>
<step_number><![CDATA[5]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
<step>
<step_number><![CDATA[6]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
</steps>
</testcase>
</testsuite></testsuite></testsuite><testsuite id="4599" name="testsuite2" >
<node_order><![CDATA[0]]></node_order>
<details><![CDATA[]]></details>
<testcase internalid="4600" name="single testcase">
<node_order><![CDATA[0]]></node_order>
<externalid><![CDATA[1081]]></externalid>
<version><![CDATA[1]]></version>
<summary><![CDATA[<p>description<p/>]]></summary>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<execution_type><![CDATA[1]]></execution_type>
<importance><![CDATA[0]]></importance>
<estimated_exec_duration></estimated_exec_duration>
<status>1</status>
<is_open>1</is_open>
<active>1</active>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>step1<p/>]]></actions>
<expectedresults><![CDATA[<p>except1<p/>]]></expectedresults>
<execution_type><![CDATA[1]]></execution_type>
</step>
</steps>
</testcase>
</testsuite></testsuite>
在testlink里面的展示结构如下图:
图1
从xml结构中我们可以看出一个testsuite里面还可以嵌套testsuite,testsuite里面然后嵌套testcase,testcase里面嵌套steps,step再嵌套step,一个testsuite在testlink里面表现为一个文件夹,如上图所示,testcase表现为1条测试用例,steps表示测试步骤。当然testcase里面还会包含用例的摘要(summary),前提(preconditions),优先级(importance),然后step里面包含步骤编号(step_number),步骤(action),期望结果(exceptedresults),而1个操作步骤可能包含多个子步骤,其中使用<p><p/>嵌套的文本表示在testlink中显示为一个独立的段落。
经过小编分析验证,这个原始testlink xml里面的数据并不是都需要才能导入到testlink里面,下面是小编提取的一个模板(都是必须字段):
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testsuite name="testsuite1">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testsuite name="testsuite2">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testsuite name="testsuite3">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testcase name="testcase in deep folder">
<node_order><![CDATA[]]></node_order>
<summary><![CDATA[<p>description<p/>]]></summary>
<importance><![CDATA[level1]]></importance>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
</steps>
</testcase>
</testsuite>
</testsuite>
</testsuite>
<testsuite name="testsuite2">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testcase name=" single testcase">
<node_order><![CDATA[]]></node_order>
<summary><![CDATA[<p>description<p/>]]></summary>
<importance><![CDATA[level1]]></importance>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>step1<p/>]]></actions>
<expectedresults><![CDATA[<p>except1<p/>]]></expectedresults>
</step>
</steps>
</testcase>
</testsuite>
<testsuite name="testsuite1">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testsuite name="testsuite2">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testsuite name="testsuite3">
<node_order><![CDATA[]]></node_order>
<details><![CDATA[]]></details>
<testcase name="testcase with more than one step ">
<node_order><![CDATA[]]></node_order>
<summary><![CDATA[<p>description<p/>]]></summary>
<importance><![CDATA[level1]]></importance>
<preconditions><![CDATA[<p>prediction<p/>]]></preconditions>
<steps>
<step>
<step_number><![CDATA[1]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
<step>
<step_number><![CDATA[2]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
<step>
<step_number><![CDATA[3]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
<step>
<step_number><![CDATA[4]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
<step>
<step_number><![CDATA[5]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
<step>
<step_number><![CDATA[6]]></step_number>
<actions><![CDATA[<p>1、step<p/><p>2、step<p/><p>3、step3<p/>]]></actions>
<expectedresults><![CDATA[<p>1、except<p/><p>2、except<p/><p>3、excepet<p/>]]></expectedresults>
</step>
</steps>
</testcase>
</testsuite>
</testsuite>
</testsuite>
</testsuite>
这个简化的xml就是小编使用的Excel测试用例模板解析后的结果,小编使用的模板如下:
图2
测试案例路径使用反斜杠“/”分割,如果此列中没有使用“/”分割则在testlink中默认为一个单独的文件夹,如上图图1所示
实现方式
小编这里使用了java中比较流行的dom4j来生成xml文档,使用Apache poi来解析Excel提取数据,小编使用的是maven 工程,pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>testlink</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>testlink</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
</project>
主要有2个类:Excel2Xml负责Xml文档创建,ExcelUtil负责Excel文件相关的,当然小编读取Excel也是在Excel2Xml这个类中写的。
代码如下:
package com.testlink;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class Excel2Xml {
public Excel2Xml() {
}
static int stepNum = 1;// 用例步骤
static String filePath;
//static String testLinkXmlFile;
static File testLinkXmlFile;
// static String filePath = "input.xlsx";
// static String testLinkXmlFile = "output.xml";
// public static void setTestLinkXmlFile(String testLinkXmlFile) {
// Excel2Xml.testLinkXmlFile = testLinkXmlFile;
// }
public static File getTestLinkXmlFile() {
return testLinkXmlFile;
}
public static void setTestLinkXmlFile(File testLinkXmlFile) {
Excel2Xml.testLinkXmlFile = testLinkXmlFile;
}
public static String getFilePath() {
return filePath;
}
public static void setFilePath(String filePath) {
Excel2Xml.filePath = filePath;
}
public static void main(String[] args) {
writeXmlFile(testLinkXmlFile);
}
/**
* 写出testlink xml文件
*/
public static void writeXmlFile(File testLinkXmlFile) {
try {
OutputFormat format = OutputFormat.createPrettyPrint();
//FileWriter out = new FileWriter(testLinkXmlFile);//
//使用FileWriter会出现打包后乱码,改用FileOutputStream
FileOutputStream out=new FileOutputStream(testLinkXmlFile);
Document document = parseTestCase(filePath,false);
XMLWriter writer2File;
writer2File = new XMLWriter(out, format);
writer2File.write(document);
out.close();
// 美化文档格式输出到System.out
XMLWriter writer;
writer = new XMLWriter(System.out, format);
writer.write(document);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/**
*
* @param filePath
* excel测试用例路径
* @return xml Document对象
*/
@SuppressWarnings("deprecation")
public static Document parseTestCase(String filePath,boolean isView) {
// DataFormatter formatter = new DataFormatter();
Workbook workbook = ExcelUtil.readExcel(filePath);// 读取Excel文件
Sheet caseSheet = workbook.getSheetAt(0);// 获取解析用例的表格
Document document = DocumentHelper.createDocument();
// 设置xml根节点属性
Element root = document.addElement("testsuite");
root.addAttribute("name", "");// 添加name属性
// 设置xml头信息
Element nodeOrder = root.addElement("node_order");
nodeOrder.addCDATA("");
Element details = root.addElement("details");
details.addCDATA("");
System.out.println("最大行数为:" + caseSheet.getLastRowNum());
Element testsuiteChildNodes = null;
Element testCase = null;
Element steps = null;
// 从第二行开始读取,遍历整个用例表
StringBuffer buf=new StringBuffer("");
for (int pathRow = 1; pathRow <=caseSheet.getLastRowNum(); pathRow++) {
Element parent = root; // 将parent设置为根目录
System.out.println(
"==========================当前为第" + pathRow + "次循环===========================================");
Row currentRow = caseSheet.getRow(pathRow);
Cell testsuiteCell = currentRow.getCell(0);// 获取案例路径
// 获取testsuite的值
try {
if (testsuiteCell.getCellType() == Cell.CELL_TYPE_STRING) {
String path_str = testsuiteCell.getStringCellValue();
System.out.println(testsuiteCell.getRichStringCellValue().getString());
// 如果用例包含多层路径
if (path_str.contains("/")) {
String[] path = path_str.split("/");
for (String str : path) {
System.out.println("str====================" + str);
String dirName = str;
testsuiteChildNodes = parent.addElement("testsuite").addAttribute("name", dirName);
testsuiteChildNodes.addElement("node_order").addCDATA("");
testsuiteChildNodes.addElement("details").addCDATA("");
parent = testsuiteChildNodes;// 替换父节点
}
} else {
// 不包含多层路径
testsuiteChildNodes = parent.addElement("testsuite").addAttribute("name", path_str);
testsuiteChildNodes.addElement("node_order").addCDATA("");
testsuiteChildNodes.addElement("details").addCDATA("");
parent = testsuiteChildNodes;// 替换父节点
}
}
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
// 获取用例名称
Cell caseCell = currentRow.getCell(1);// 获取用例名称
System.out.println("第" + pathRow + "次循环========================================用例名称为:"
+ caseCell.getStringCellValue());
Cell summaryCell = currentRow.getCell(2);// 获取摘要
System.out.println("第" + pathRow + "次循环========================================摘要名称为:"
+ summaryCell.getStringCellValue());
Cell stepCell = currentRow.getCell(5);// 获取步骤
System.out.println("步骤为:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" + stepCell.getStringCellValue());
// 设置预期结果
Cell expectedresultsCell = currentRow.getCell(6);
System.out.println("期望为:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" + expectedresultsCell.getStringCellValue());
String caseName = null;// 用例名称
if (caseCell.getCellType() == Cell.CELL_TYPE_STRING && caseCell.getCellType() != Cell.CELL_TYPE_BLANK) {
stepNum = 1;
if (caseCell.getStringCellValue() != null) {
caseName = caseCell.getStringCellValue();
testCase = testsuiteChildNodes.addElement("testcase").addAttribute("name", caseName);
testCase.addElement("node_order").addCDATA("");
String summaryName = null;
if (summaryCell.getCellType() == Cell.CELL_TYPE_STRING
&& summaryCell.getCellType() != Cell.CELL_TYPE_BLANK) {
summaryName = summaryCell.getStringCellValue();
testCase.addElement("summary").addCDATA("<p>" + summaryName + "<p/>");
}
// 获取优先级
Cell importanceCell = currentRow.getCell(3);// 获取优先级
String importance = null;
if (importanceCell.getCellType() == Cell.CELL_TYPE_STRING
&& importanceCell.getCellType() != Cell.CELL_TYPE_BLANK) {
importance = importanceCell.getStringCellValue();
testCase.addElement("importance").addCDATA(importance);
}
// 获取前提,前提不为空
Cell preconditionsCell = currentRow.getCell(4);// 获取前提
String preconditions = null;
if (preconditionsCell.getCellType() == Cell.CELL_TYPE_STRING
&& preconditionsCell.getCellType() != Cell.CELL_TYPE_BLANK) {
preconditions = preconditionsCell.getStringCellValue();
testCase.addElement("preconditions").addCDATA("<p>" + preconditions + "<p/>");
}
// 前提为空的 情况
if (preconditionsCell.getCellType() == Cell.CELL_TYPE_BLANK) {
testCase.addElement("preconditions").addCDATA("<p><p/>");
}
// 添加步骤标签
steps = testCase.addElement("steps");
}
}
if (caseName == null && caseCell.getCellType() == Cell.CELL_TYPE_BLANK) {
stepNum++;
System.out.println("================================stepNum的值为:" + stepNum);
}
String step = null;
if (stepCell.getCellType() == Cell.CELL_TYPE_STRING) {
// 获取步骤中的描述
step = stepCell.getStringCellValue();
System.out.println("########################步骤为:" + step);
// 如果有多个操作步骤
step = step.replaceAll("\n", "");// 替换所有的换行符
}
String expectedresults = null;
if (expectedresultsCell.getCellType() == Cell.CELL_TYPE_STRING) {
expectedresults = expectedresultsCell.getStringCellValue();
// // 获取步骤中的描述
Element actionStep = steps.addElement("step");
// // 设置步骤顺序
actionStep.addElement("step_number").addCDATA(Integer.toString(stepNum));
System.out.println("*************************************" + stepNum);
System.out.println("当前用例:<" + caseName + "> 步骤数为" + stepNum);
// 设置步骤
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@操作步骤为:" + step);
// 如果有多个操作步骤
if(step!=null) {
if (HasDigit(step)&&step.startsWith("1、")) {
step = splitMuiltyStep(step);
System.out.println("多步操作******************************************多步操作" + step);
actionStep.addElement("actions").addCDATA(step);
}else {
actionStep.addElement("actions").addCDATA("<p>" + step + "<p/>");
}
}
if(step==null) {
//
buf.append("第"+pathRow+"行操作步骤为空,请确认!"+"\n");
}
// 设置预期结果
System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$期望结果为:" + expectedresults);
// 如果期望结果有多个
expectedresults = expectedresults.replaceAll("\\n", "");
System.out.println("期望结果&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" + expectedresults);
if(expectedresults!=null) {
if (HasDigit(expectedresults)&&expectedresults.startsWith("1、")) {
expectedresults = splitMuiltyStep(expectedresults);
System.out.println(expectedresults);
System.out.println("多步操作******************************************多步操作" + expectedresults);
actionStep.addElement("expectedresults").addCDATA(expectedresults);
} else {
System.out.println("_____________________没有多个期望");
actionStep.addElement("expectedresults").addCDATA("<p>" + expectedresults + "<p/>");
}
}
}
if(pathRow==caseSheet.getLastRowNum()) {
new ExceptionDialog(null, buf.toString(),null,isView);
}
}
return document;
}
/**
* 分割多步骤,多期望的用例
* @param stepStr
* 多步操作的字符串
* @return 解析后的多步操作
*/
public static String splitMuiltyStep(String stepStr) {
String regex = "\\d+、";
String newStep = "";
String arry[] = stepStr.split(regex);
for (int i = 0; i < arry.length; i++) {
if (i != 0) {
System.out.println(arry[0]);
System.out.println("<p>" + i + "、" + arry[i] + "<p/>");
newStep += "<p>" + i + "、" + arry[i] + "<p/>";
}
}
return newStep;
}
/**
* 判断字符串中是否存在数字
* @param content
* @return
*/
public static boolean HasDigit(String content) {
boolean flag = false;
Pattern p = Pattern.compile(".*\\d+.*");
Matcher m = p.matcher(content);
if (m.matches()) {
flag = true;
}
return flag;
}
}
package com.testlink;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelUtil {
private static String fileOutPutFordler;
public static String getFileFordler() {
return fileOutPutFordler;
}
public static void setFileFordler(String fileFordler) {
fileOutPutFordler = fileFordler;
}
public ExcelUtil() {
}
// 读取excel
/**
*
* @param filePath 读取文件的路径
* @return
*/
@SuppressWarnings("resource")
public static Workbook readExcel(String filePath) {
Workbook wb = null;
if (filePath == null) {
return null;
}
String extString = filePath.substring(filePath.lastIndexOf("."));
InputStream is = null;
try {
is = new FileInputStream(filePath);
if (".xls".equals(extString)) {
return wb = new HSSFWorkbook(is);
} else if (".xlsx".equals(extString)) {
return wb = new XSSFWorkbook(is);
} else {
return wb = null;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return wb;
}
/***
*打开文件、文件夹
* @param folder
* : directory
*/
public static void open_directory(String folder) {
File file = new File(folder);
if (!file.exists()) {
return;
}
Runtime runtime = null;
try {
runtime = Runtime.getRuntime();
runtime.exec("cmd /c start explorer " + folder);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (null != runtime) {
runtime.runFinalization();
}
}
}
}
注意事项:
1、用例路径名称中不要包含反斜杠”/”否则会解析为文件夹,用例路径中不包含“/”会解析为单个文件夹
2、用例只有一条步骤和结果的,用例路径不能为空,用例名称不能为空
3、用例包含多条操作步骤或者多条期望结果请以“1、”开头;另外步骤、期望中除了包含多步操作或期望结果用数字加顿号作为步骤操作外,
其他语句中如果包含要使用顿号“、”请尽量使用逗号“,”(不区分中英文,顿号之外的其他符号都可以)替代且第一条用例标题不能为空
4、所有字段请不要使用合并单元格
5、用例模板:A-G对应Excel中的列号
A:用例路径 (不能为空)B:用例标题(单步操作不能为空,多不操作第一条用例不能为空) C:摘要 D:优先级 E:前置条件 F:操作步骤(不能为空) G:期望结果(不能为空)
6、请不要创建多余的Excel单元格,创建多余的单元格将不能正常生成testlink xml文件
7、请保证Excel单元格格式的一致性(要么都设置了边框,要么都不设置),否则可能出现不可预知的错误
以上就是全部内容了,小编原创,转载请注明出处谢谢~