Automated testing is now becoming more and more platform-oriented, platform is committed to work together to improve efficiency, so that more people participate in the process of automation, in my opinion, the platform, there is a more critical point, is the keyword driver, only the automated testing of the code into a more easy to understand the natural language, In order to let more people do not understand the code to join in order to achieve the purpose of platform. Today we're going to talk about the principle and implementation of keyword-driven in automated testing.
First look at an example, the teacher said to the students: go to the table from a location to the B location. When the teacher issued this order, found that no one moved, because there is no clear object, do not know who the order is issued to whom, so the teacher said again: Zhang San, to the table from a location to the B location. At this time, with a definite object-Zhang San, the subject of the command-move the table from a to B. So the phrase "Zhang San, to move the table from location A to place B," There are two keywords: Zhang San, the table from a location to the B location. When these two keywords are missing any one, it is impossible to complete this thing. So, we can think of this scenario as a keyword driver, if we convert the above sentence into code:
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 ("Zhang San"); md.movedeskfroma2b ();}}
The above code is of course pseudo-code, but it can be seen that in order to achieve a purpose, the process is the same, the two keywords in the main method is reflected as: Zhang San corresponding to Md. Setzhangsan ("Zhang San"), "move the table from location A to location B" corresponding to MD.MOVEDESKFROMA2B (). Thus we can understand this: Each keyword corresponds to a specific method. So, summarize the implementation features of the keyword driver:
1. Each keyword corresponding to the method (hereinafter referred to as the key method) must be able to be called at any time, as the teacher's command to Zhang San Zhang San must be executed. In Java in order to achieve this key method can be called at any time, its class object must be new good, so there is a pool of objects, this object pool like a class, there are many students can be issued by the teacher command and to execute.
2. Keywords must be associated with key methods, just like the teacher let Zhang San move the table, and Zhang San ran to buy a pack of cigarettes, which is not right, so, must have a keyword and the key method of the mapping table.
3. There must be a keyword parsing method, such as the above command, we want to be able to draw Zhang San, the table from a location to the B location of the two keywords, if not to derive the keyword, the key method will be less executed, as in the above pseudo-code, if the MD is removed. Setzhangsan ("Zhang San") This sentence, obviously will be reported null pointer exception.
4. The above three has been implemented, the teacher issued an order, Zhang three to be able to carry out, of course, if Zhang three is a thorn head said otherwise. Java code can be handed to the JVM to execute, but after converting to a keyword, the JVM does not recognize these keywords, so we also have to have a robust execution engine, so that "Zhang San, to move the table from a location to the B location," This sentence can be executed successfully.
To sum up, as long as we put the above four through the code to achieve, a simple keyword framework of the prototype came out, the next one of the implementation of the strip.
1. Object pool:
public class Registercenter {public static map<string, object> obj_pools = new hashmap<string, object> (); stat Ic{obj_pools.put (MoveDesk.class.getName (), New Movedesk ());}}
Initialize all classes that contain the critical methods, and then place them in the Obj_pools object, and call the key methods directly behind them. (Please try to use annotations to achieve, will be more dazzling)
2. Mapping Table:
public class Keywordreflect {public static map<string, map<string, string>> keyword_pools = new Hashmap<st Ring, Map<string, string>> () static{keyword_pools.put ("Zhang San", Keywordreflect.methodinfo ( MoveDesk.class.getName (), "Setzhangsan")); Keyword_pools.put ("Move table from location A to location B", Keywordreflect.methodinfo (MoveDesk.class.getName (), "movedeskfroma2b")); public static map<string, string> methodInfo (String className, String methodName) {map<string, string> MethodInfo = new hashmap<string, string> (), Methodinfo.put ("Class", ClassName), Methodinfo.put ("Method", MethodName); return methodInfo;}}
Description: The data structure of the Keyword_pools object above is a map nested in the map, this is because to clarify the class object, because different classes may have the same name method, so in order to avoid confusion, must be labeled good one method class and method name, so as to establish a good one by one mapping table. (also can be implemented with annotations)
3. Parsing keywords
In order to be able to parse out the keywords, we have to "Zhang San, go to the table from a location to the B location," The keyword to mark out, to change the "${Zhang San}, to ${the table from a location to the B place}", so that the keyword to clear the label out, although from the intuitive feeling of a little bit worse, But it's a very important part of the keyword drive. The next question turns into a parsing of ${} in a string:
Regular class:
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; } }
Get the keyword class:
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}"));}}
Note: The use of the regular pre-check mode, the regular pre-check mode is a relatively high-level usage of the regular, after mastering this, your regular will be a step.
4. Execution Engine:
The execution engine first to find the need to execute the statement, so, the teacher should first send the command to read out, this command can be stored in any format file, as long as can be read out, here we save in Command.txt:
Read this command:
public class Executor {public list<string> readtxtfile (String filePath) {list<string> List = new Arraylist< ; String> (); try {String encoding = "UTF8"; File File = new file (FilePath); if (File.isfile () && file.exists ()) {InputStreamReader read = new InputStreamReader (New fileinputs Tream (file), encoding); BufferedReader BufferedReader = new BufferedReader (read); String linetxt = null; while ((Linetxt = Bufferedreader.readline ()) = null) {List.add (linetxt); } read.close (); Bufferedreader.close (); } else {System.out.println ("The specified file cannot be found"); }} catch (Exception e) {System.out.println ("Error reading file contents"); E.printstacktrace (); } return list; }public static void Main (string[] args) {Executor e = new Executor (); System.out.println (E.readtXtfile ("Src/command.txt"));}}
After reading, the process is: get keyword, get key method, and execute the key method.
public class Executor {private Parsekeyword pk = new Parsekeyword ();p ublic list<string> readtxtfile (String filePath ) {list<string> List = new arraylist<string> (); try {String encoding = "UTF8"; File File = new file (FilePath); if (File.isfile () && file.exists ()) {InputStreamReader read = new InputStreamReader (New fileinputs Tream (file), encoding); BufferedReader BufferedReader = new BufferedReader (read); String linetxt = null; while ((Linetxt = Bufferedreader.readline ()) = null) {List.add (linetxt); } read.close (); Bufferedreader.close (); } else {System.out.println ("The specified file cannot be found"); }} catch (Exception e) {System.out.println ("Error reading file contents"); E.printstacktrace (); } return list; }public void executor () {list<string> commands = This.readtxtfile ("Src/command.txt"); for (String command:commands) {list<string> keywords = pk.getkeywords ( command); for (String keyword:keywords) {this.invoke (keyword);}}} 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 = This.getmethod (MethodName, obj); try {method.invoke (obj);} catch (Illegalaccessexception | IllegalArgumentException | InvocationTargetException e) {e.printstacktrace ();}} Private Method GetMethod (String methodName, Object obj) {try {method[] methods = Obj.getclass (). GetMethods (); for (Method m : Methods) {if (M.getname (). Equals (MethodName)) {return m;}}} catch (SecurityException e) {return null;} return null;} public static void Main (string[] args) {Executor e = new Executor (); E.executor ();}}
For everyone to see the results of the implementation, the Movedesk class to change:
public class Movedesk {public void Setzhangsan () {System.out.println ("This is Zhangsan");} public void movedeskfroma2b () {System.out.println ("This is test!");}}
Once this is done, you can see that the two key method bodies are executed! The most critical thing in the execution engine is the use of Java's reflection to execute the method!
The above code passes through the test run!
From this one of the most simple keyword driver rack is completed, there are some of the following points need to be done by ourselves: Key method parameter processing, key method return value processing, exception processing, combined with data driven, combined with the test framework (TESTNG/JUNIT). There is also a lot of optimization space for everyone to play on their own!
The principle and implementation of automatic test keyword driving