首页 文章 精选 留言 我的

精选列表

搜索[项目自动化],共10014篇文章
优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - DataProviderEngine架构

为了基于上文我们的xml文件的架构,对其进行解析,我自己写了一个DataProviderEngine作为解析xml文件的引擎,它主要的架构如下图: 具体细节如下,为了节省时间,我直接复制我的英文邮件内容了: Step 1: The XMLReader read the raw test suite xml file (now we adopt the xml file ,since it is not binary file and easy to edit and version control) Step 2: After reading ,XMLReader store the xml string into a string variable named “ originalXmlString “, this is our starting point. Step 3: The XIncludeConverter read the originalXmlString ,and resolve the XInclude namespace ,when it resolve this file ,it will replace all the <xi:include href> element with the actual xml fragments one by one. Step 4: After replacing all <xi:include> ,XIncludeConverter will store the new xml string into string variable named “convertedXmlString”. Step 5: The XMLManipulator read the convertedXmlString ,and remove all the user configuration part from such as <add_elements>,<update_elements>,<remove_elements> ,since these information is used for letting test case end user configure how to operate the base data to meet special requirements,so these part shouldn’t exist in final data. Step 6:After removing all config elements ,The XMLManipulator store the xml string into a new string variable named “ removeAllConfXmlString” Step 7:Since the configuration information are removed in Step 5-6 ,but they still exist in original xml string ,so XMLModifyInfoExtractor read all the <add_elements>,<update_elements>,<remove_elements> part from original xml string ,and smartly match which corresponding testcase data it will operate . Step 8:After analyzing all the user modification requirement ,the XMLModifyInfoExtractor store these modification info into 3 arraylists , addElementInfoList,updateElementInfoList,removeElementInfoList. Step 9:Now it is time to begin modifying the xml ,so the XMLManipulator read the “removeAllConfXmlString” in Step 6 . Step 10:Then XMLManipulator use all the modification info in Step 8 ,and do modification operation one by one : addElementToXML() ,updateElementFromXML(),removeElementFromXML() Step 11: after finish all the modification ,XMLManipulator store the final xml string into string variable named “modifiedXmlString” Step 12: Finally it convert the xml formatted string to a jsonobject and it now can be used as a data provider which can be consumed in each test case. 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221708,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - 解析XInclude标记

因为在test_suite.xml中,我们多处使用了XInclude标记,他们会被申明在一个叫"http://www.w3.org/2001/XInclude"的名字空间中,并且引入部分用xi:include来声明,我们这个类的作用就是把这些所有的<xi:include>的部分,都用被引入的文件插入和替换掉。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /** * This class will handle converting a xinclude+xpointer marked xml file to a normal xml file * Because of the shortage of the current jdk ,it only support the xPointer with element instead of NCName *@author cwang58 *@created date: Jun 10, 2013 */ public class XIncludeConverter { /** * this method will handle change the XInclude+XPointer marked xml as normal xml * @param origialXML the original xml which has the xInclude feature * @return the parsedXML without the xInclude feature */ public static String convertXInclude2NormalXML(String originalXML) throws SAXException,ParserConfigurationException,TransformerConfigurationException,IOException,TransformerException{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //open up the namespace aware so that it can recognize the "xi" namespace factory.setNamespaceAware( true ); //let this SAXParser support XInclude factory.setXIncludeAware( true ); //factory.setValidating(true); //ignore all the comments added in the source document factory.setIgnoringComments( true ); DocumentBuilder docBuilder = factory.newDocumentBuilder(); Document doc = docBuilder.parse( new InputSource( new ByteArrayInputStream(originalXML.getBytes( "utf-8" )))); Transformer transformer = TransformerFactory.newInstance().newTransformer(); //format the output xml string so it support indent and more readable transformer.setOutputProperty(OutputKeys.INDENT, "yes" ); //initialize StreamResult with File object to save to file StreamResult result = new StreamResult( new StringWriter()); DOMSource source = new DOMSource(doc); transformer.transform(source, result); return result.getWriter().toString(); } 这里讲一个小插曲,其实,W3C中,XInclude经常和Xpointer联合起来应用的,xpointer可以帮助来定位目标文件的某个小片段而不是整个目标文件,定位方法可以用element(),或者xpointer(),如果element的话,可以用(/1/2/3)这种方式来定位DOM,或者基于 id,对应java的解析框架是xerce,但是非常不幸运的是,最新版本的xerce框架只支持element(/1/3/4/5)这种定位,而对于基于schema-id的方式,也就是某个element声明了id的情况,它没办法定位,但是未来可能会支持这个功能。 http://xerces.apache.org/xerces2-j/faq-xinclude.html#faq-8 基于上述的局限性,我决定只采用xi:include来包含全部文件,然后局部调整的做法,并且绕过xpointer。 所以实现代码如上所示,事实上从JDK 1.6开始,他已经提供了对XInclude的支持,内部是委托给xerce来实现的,这是对应架构图的第3-4步骤。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221731,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - 去除动作指令

因为我们在test_suite.xml中定义了多个动作指令,比如<add_elements>,<update_elements>等,他们指示让我们Engine来对最终数据进行操作,这些动作指令不是数据,因此,他们并不包含在我们最终的数据结果集中,所以我们必须对他们进行移除。所以我们用以下代码来进行移除工作: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class XMLManipulator { public static String removeModifyConfFromXML(String xmlString) throws Exception{ Document doc = null ; doc = DocumentHelper.parseText(xmlString); //remove the <add_elements> from the target xml List<Node> addPart = doc.selectNodes( "/test_suite/test_case/add_elements" ); for (Node node: addPart){ node.getParent().remove(node); } //remove the <add_elements> from the target xml List<Node> updatePart = doc.selectNodes( "/test_suite/test_case/update_elements" ); for (Node node: updatePart){ node.getParent().remove(node); } //remove the <remove_elements> from the target xml List<Node> removePart = doc.selectNodes( "/test_suite/test_case/remove_elements" ); for (Node node: removePart){ node.getParent().remove(node); } //find document again return doc.asXML(); } .. } 这样最终的xml文件就不包含这些动作指令的代码片段了。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221739,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - 读取原始xml文件

按照我们的架构,第一步是读取原始的xml文件到一个xml字符串中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 /** * *@author cwang58 *@created date: Jun 10, 2013 */ public class XMLReader { private static final String LINE_SEPARATOR=System.getProperty( "line.separator" ); private static String userDir = System.getProperty( "user.dir" ); private static final String fileSeparator=System.getProperty( "file.separator" ); private static final String dataFileName= "test_suite.xml" ; /** * build the data file path which depends on the platform * @param projectName * @return */ public static String buildDataFilePath (String projectName){ return userDir+fileSeparator+ "src" +fileSeparator+ "test" +fileSeparator+ "resources" +fileSeparator+projectName +fileSeparator+ "data" +fileSeparator+dataFileName; } /** * read the file content then store contant into a string * @param source the file source name * @return * @throws IOException */ public static String readContentFromFile(String source) throws IOException{ File file = new File(source); // open a file reader to read the file content FileInputStream fis = null ; InputStreamReader isr = null ; BufferedReader reader = null ; try { fis = new FileInputStream(file); isr = new InputStreamReader(fis, "utf-8" ); reader = new BufferedReader(isr); StringBuffer bufferedFileContent = new StringBuffer(); String line = null ; while ((line = reader.readLine()) != null ) { bufferedFileContent.append(line).append(LINE_SEPARATOR); } return bufferedFileContent.toString(); } catch (FileNotFoundException ex) { ex.printStackTrace(); return null ; } finally { if (reader!= null ) reader.close(); if (isr!= null ) isr.close(); if (fis!= null ) fis.close(); } } 代码很简单,就是一个基于文件流的操作,不再自己讲解。这个步骤对于架构图的第一步。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221718,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - XML格式转为json格式

因为讨论下来,最终的DataProvider格式需要是一个json格式,所以我们还必须提供方法吧xml格式转为json格式,现在很多框架比如json-lib框架能很轻易的完成这个任务了。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * This class will read the xml file and then change it to a json object *@author cwang58 *@created date: Jun 9, 2013 */ public class XMLJSONConverter { /** * This method will convert the xml to json object * @param xml the xml string * @return the json string */ public static String xml2JSON(String xml){ XMLSerializer xmlSerializer = new XMLSerializer(); JSON json = xmlSerializer.read(xml); return json.toString(); } .. } 就几行代码,很容易读懂。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221759,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - 分离出动作指令信息

但是,我们这些动作指令信息毕竟是让测试用例数据的设计者告诉Engine怎样修改原始数据集合的,所以我们必须把这些信息分离出来,但是刚才一步骤,已经把这些片断移除了,那么怎么把这些信息拿到呢?很简单,不是我们有原始数据么,所以我们就可以对于原始数据的xml字符串,一个testcase,一个testcase的吧这些动作指令解析出来并且存放在相应的Value Object 列表中,以后我们只要根据这些列表中提供的信息就可以正确的对于原来的数据集合进行操作了。 分离信息的类叫XMLModifyInfoExtractor,它负责分离动作: 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 /** * extract all the modification information and store to member fields. * @param filePath * @throws Exception */ public void extractModifyInfo(String filePath) throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read( new File(filePath)); Element rootElement = document.getRootElement(); String testcaseElementPathValue; Element addElements; Element addElementPath; String addElementPathValue; Element addElementValue; String addElementValueValue; Element updateElements; Element updateElementPath; String updateElementPathValue; Element updateElementValue; String updateElementValueValue; Element removeElements; Element removeElementPath; String removeElementPathValue; //first ,get all the <test_case> element List<Element> testcaseElementList = rootElement.elements( "test_case" ); for (Element testcaseElement : testcaseElementList){ testcaseElementPathValue = testcaseElement.getUniquePath(); //get <add_elements> part from the <test_case> addElements= testcaseElement.element( "add_elements" ); if (addElements!= null ){ //traverse the <add_elements> to get a seris of <add_element> List<Element> addElementList = addElements.elements( "add_element" ); for (Element addElement : addElementList){ //extract the <path> information from <add_element> addElementPath = addElement.element( "path" ); addElementPathValue = addElementPath.getTextTrim(); //extract the <value> information from <add_element> addElementValue = addElement.element( "value" ); String xmlValue=addElementValue.asXML(); //remove the <value> and </value> part from this xml addElementValueValue=xmlValue.replace( "<value>" , "" ).replace( "</value>" , "" ); addElementInfoList.add ( new AddElement(testcaseElementPathValue,addElementPathValue,addElementValueValue)); } } //get <update_elements> part from the <test_case> updateElements= testcaseElement.element( "update_elements" ); if (updateElements!= null ){ //traverse the <update_elements> to get a seris of <update_element> List<Element> updateElementList = updateElements.elements( "update_element" ); for (Element updateElement : updateElementList){ //extract the <path> information from <update_element> updateElementPath = updateElement.element( "path" ); updateElementPathValue = updateElementPath.getTextTrim(); //extract the <value> information from <update_element> updateElementValue = updateElement.element( "value" ); updateElementValueValue=updateElementValue.getTextTrim(); updateElementInfoList.add ( new UpdateElement(testcaseElementPathValue,updateElementPathValue,updateElementValueValue)); } } //get <remove_elements> part from the <test_case> removeElements= testcaseElement.element( "remove_elements" ); if (removeElements != null ){ //traverse the <remove_elements> to get a seris of <remove_element> List<Element> removeElementList = removeElements.elements( "remove_element" ); for (Element removeElement : removeElementList){ //extract the <path> information from <remove_element> removeElementPath = removeElement.element( "path" ); removeElementPathValue = removeElementPath.getTextTrim(); removeElementInfoList.add( new RemoveElement(testcaseElementPathValue,removeElementPathValue)); } } } } 现在经过上述3步骤之后,我们的代码中所有的动作序列的执行内容都被存放在相应变量中了。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221749,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - 对于内容文件动作指令信息

我们分为3个方法依次对于<add_elements>,<update_elements>,<remove_elements>进行解析: 对于<add_elements>内部遍历解析的代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /** * add the new information which configured in original xml and finally generate the new xml */ publicstaticString addElementToXML(String xmlString ,XMLModifyInfoExtractor extractor,String originalFilePath) throwsException{ Document doc = null ; doc = DocumentHelper.parseText(xmlString); extractor.extractModifyInfo(originalFilePath); //All the add information are provided by XMLModifyInfoExtractor List<AddElement> addElementInfoList = extractor.getAddElementInfoList(); List<Node> nodes ; for (AddElement addElement : addElementInfoList){ String testcaseXPath =addElement.getTestcaseXPath(); String path =addElement.getPath(); String value=addElement.getValue(); //make the value as a Element block Element newElementSnippet = DocumentHelper.parseText(value).getRootElement(); nodes = doc.selectNodes(path); for (Node node :nodes){ //if in the node is in matching testcase ,then remove it String nodeUniquePath = node.getUniquePath(); if (nodeUniquePath.indexOf(testcaseXPath) !=- 1 ){ //node.getParent().remove(node); //node.setText(value); Element addingPointElement = (Element) node; addingPointElement.add(newElementSnippet); } } } returndoc.asXML(); } 对于<update_elements>内部元素进行遍历的代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 /** * update the information which configured in original xml and finally generate the new xml */ publicstaticString updateElementFromXML(String xmlString ,XMLModifyInfoExtractor extractor,String originalFilePath) throwsException{ Document doc = null ; doc = DocumentHelper.parseText(xmlString); extractor.extractModifyInfo(originalFilePath); //All the update information are provided by XMLModifyInfoExtractor List<UpdateElement> updateElementInfoList = extractor.getUpdateElementInfoList(); List<Node> nodes ; for (UpdateElement updateElement : updateElementInfoList){ String testcaseXPath =updateElement.getTestcaseXPath(); String path =updateElement.getPath(); String value=updateElement.getValue(); nodes = doc.selectNodes(path); for (Node node :nodes){ //if in the node is in matching testcase ,then remove it String nodeUniquePath = node.getUniquePath(); if (nodeUniquePath.indexOf(testcaseXPath) !=- 1 ){ node.setText(value); } } } returndoc.asXML(); } 对于<remove_elements>中元素进行遍历解析的代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /** * remove the information which configured in original xml and finally generate the new xml */ publicstaticString removeElementFromXML(String xmlString ,XMLModifyInfoExtractor extractor,String originalFilePath) throwsException{ Document doc = null ; doc = DocumentHelper.parseText(xmlString); extractor.extractModifyInfo(originalFilePath); //All the remove information are provided by XMLModifyInfoExtractor List<RemoveElement> removeElementInfoList = extractor.getRemoveElementInfoList(); List<Node> nodes ; for (RemoveElement removeElement : removeElementInfoList){ String testcaseXPath =removeElement.getTestcaseXPath(); String path =removeElement.getPath(); nodes = doc.selectNodes(path); for (Node node :nodes){ //if in the node is in matching testcase ,then remove it String nodeUniquePath = node.getUniquePath(); if (nodeUniquePath.indexOf(testcaseXPath) !=- 1 ){ node.getParent().remove(node); } } } returndoc.asXML(); } 最后,当执行3步骤动作系列转化之后,最终的xml文件就是包含最终的我们修改后的结果了。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221752,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册