个人理解自动化测试中关键字驱动的目的就是为了让更多的人参与到自动化测试中来,提高测试效率,关键字驱动框架搭建完成时候,使用起来对没有技术基础的同学来说也是十分简单的
摘录网上的一个例子:
老师对着同学们说了一句:去把桌子从A地点搬到B地点。当老师发出这个命令后,发现没有人动,因为没有明确的对象,不知道这个命令是对谁发出的,于是老师再说了一句:张三,去把桌子从A地点搬到B地点。这时候,有了明确的对象--张三,有了命令的主体--搬桌子从A到B。所以这句” 张三,去把桌子从A地点搬到B地点”中就有两个关键字:张三、把桌子从A地点搬到B地点。当这两个关键字缺少任何一个,这件事就不可能完成。所以,我们可以把这个场景理解为关键字驱动,假如我们把上面这句话转换为代码:
这是一段伪代码,搬桌子的过程一目了然,有明确的对象,有命令的主体,这是一个最简单的关键字驱动
public class MoveDesk {
private Person zhangsan;
public void setZhangsan(Person zhangsan) {
this.zhangsan = zhangsan;
}
public void moveDeskFromA2B(){
zhangsan.getTheCommandFromTeacher();
zhangsan.findTheDeskAtA();
zhangsan.moveDeskToB();
zhangsan.notifyTeacherHadFinished();
}
public static void main(String[] args) {
MoveDesk md = new MoveDesk();
md.setZhangsan("张三");
md.moveDeskFromA2B();
}
}
所以,总结一下关键字驱动的实现特点:
1.每一个关键字对应的方法都必须能够随时被调用,这就像老师对张三发出的命令张三必须去执行一样。**在java里面为了达到这个关键方法随时能被调用,其类对象必须事先被new好,所以要有一个对象池,**这个对象池就像一个班级,有很多学生可以供老师发出命令并去执行。
2.关键字必须与关键方法相关联,就像老师让张三搬桌子,而张三跑去买了一包烟,这就不对了,所以必须要有一个关键字与关键方法的映射表。
3.得有一个关键字的解析方法,比如上面那条命令中,我们要能够得出张三、把桌子从A地点搬到B地点两个关键字才行,要是不能得出关键字,关键方法就会少执行,如果上面的伪代码中,如果去掉了md.setZhangsan(“张三”);这几句,显然就会报空指针异常。
4.上面这三条具备后,就是执行了,老师发出的命令,张三要能够执行。java代码能够交给jvm去执行,但是换成关键字后,jvm就不认识这些关键字了,所以,我们也必须要有一个健壮的执行引擎,让“张三,去把桌子从A地点搬到B地点”这一句话能够被执行成功。
综上所述,只要我们把上面的四条通过代码实现,一个简单的关键字框架出行就出来了。
1.对象池
public class RegisterCenter {
public static Map<String, Object> OBJ_POOLS = new HashMap<String, Object>();
static{
OBJ_POOLS.put(MoveDesk.class.getName(), new MoveDesk());
}
//这样写不行,因为put是个动作,必须要放在主函数中
//OBJ_POOLS.put(MoveDesk.class.getName(), new MoveDesk());
}
将所有含有关键方法的类都初始化一遍,然后放到OBJ_POOLS这个对象里面,方便后面直接调用关键方法(使用注解会更方便)
2.映射表:
public class KeywordReflect {
public static Map<String, Map<String, String>> KEYWORD_POOLS = new HashMap<String, Map<String,String>>();
static{
KEYWORD_POOLS.put("张三", KeywordReflect.methodInfo(MoveDesk.class.getName(),"setZhangsan"));//后面的是方法名
KEYWORD_POOLS.put("把桌子从A地点搬到B地点", KeywordReflect.methodInfo(MoveDesk.class.getName(), "moveDeskFromA2B"));
}
private static Map<String, String> methodInfo(String className, String methodName) {
// TODO Auto-generated method stub
Map<String, String> methodInfo = new HashMap<String, String>();
methodInfo.put("class", className);
methodInfo.put("method", methodName);
return methodInfo;
}
}
上面的KEYWORD_POOLS对象的数据结构是MAP里面套一个MAP,这是因为要明确类对象,因为不同类里面可能有相同名称的方法,所以为了避免混乱,必须标注好一个方法的类与方法名,这样才能建立好一一对应的映射表。(同样可以用注解来实现)
3.解析关键字
为了能够解析出关键字,我们得把“张三,去把桌子从A搬到B”这句话的关键字给标注出来,改造一下“${张三},去${把桌子从A搬到B}”,这样就把关键字给标注出来了,虽然从直观感受上差了那么一点点,但确实关键字驱动中很重要的一部分。接下来的问题转变成为了一段字符串中${}的解析了
正则类:
public class RegExp {
public boolean match(String reg, String str){
return Pattern.matches(reg, str);
}
public List<String> find(String reg, String str){
Matcher matcher = Pattern.compile(reg).matcher(str);
List<String> list = new ArrayList<String>();
while (matcher.find()) {
list.add(matcher.group());
}
return list;
}
}
获取关键字类
public class ParseKeyword {
public List<String> getKeywords(String p){
String reg = "(?<=(?<!\\\\)\\$\\{)(.*?)(?=(?<!\\\\)\\})";
RegExp re = new RegExp();
List<String> list = re.find(reg, p);
return list;
}
public static void main(String[] args) {
ParseKeyword p = new ParseKeyword();
System.out.println(p.getKeywords("a${a}a"));
System.out.println(p.getKeywords("a\\${a}a"));
System.out.println(p.getKeywords("a${a\\}a"));
System.out.println(p.getKeywords("a${a\\}a}a"));
System.out.println(p.getKeywords("a${a}a${"));
System.out.println(p.getKeywords("a${ab}a${a}"));
}
}
4.执行引擎:
执行引擎先要找到需要执行的语句,所以,首先应该把老师发的那个命令给读取出来,这个命令可以保存在任何形式的文件里,只要能被读取出来即可。
读取命令
public class Executor {
public List<String> readTxtFile(String filePath) {
List<String> list = new ArrayList<String>();
String encode = "UTF8";
File file = new java.io.File(filePath);
if (file.isFile()&&file.exists()) {
try {
InputStreamReader read = new InputStreamReader(new FileInputStream(file));
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while ((lineTxt = bufferedReader.readLine()) != null) {
list.add(lineTxt);
}
read.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("找不到指定文件");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return list;
}
}
读取之后,流程就是:获取关键字->获取关键方法->执行关键方法.
public class Executor {
private ParseKeyword pk = new ParseKeyword();
public List<String> readTxtFile(String filePath) {
List<String> list = new ArrayList<String>();
String encode = "UTF8";
File file = new java.io.File(filePath);
if (file.isFile()&&file.exists()) {
try {
InputStreamReader read = new InputStreamReader(new FileInputStream(file));
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while ((lineTxt = bufferedReader.readLine()) != null) {
list.add(lineTxt);
}
read.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("找不到指定文件");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return list;
}
public void invoke(String keyword){
Map<String, String> keyMethod = KeywordReflect.KEYWORD_POOLS.get(keyword);
String className = keyMethod.get("class");
String methodName = keyMethod.get("method");
Object obj = RegisterCenter.OBJ_POOLS.get(className);
Method method = this.getMethod(methodName,obj);
try {
method.invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Method getMethod(String methodName, Object obj){
Method[] method = obj.getClass().getMethods();
for (java.lang.reflect.Method m : method) {
if (m.getName().equals(methodName)) {
return m;
}
}
return null;
}
public void executor(){
List<String> commands = this.readTxtFile("");
for (String command : commands) {
List<String> keywords = pk.getKeywords(command);
for (String keyword : keywords) {
this.invoke(keyword);
}
}
}
public static void main(String[] args) {
Executor e = new Executor();
System.out.println();
}
}
https://www.cnblogs.com/zhangfei/p/5330994.html
https://www.cnblogs.com/wangwy/p/9096013.html
https://blog.csdn.net/u011541946/article/details/79200801