经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
界面自动化测试录制工具,让python selenium自动化测试脚本开发更加方便
来源:cnblogs  作者:rmticocean  时间:2024/7/29 11:05:29  对本文有异议

自动化测试中,QTP和selenium IDE都支持浏览器录制与回放功能,简单的来说就像一个记录操作步骤的机器人,可以按照记录的步骤重新执行一遍,这就是脚本录制。
个人觉得传统录制工具有些弊端,加上要定制支持我自己的自动化框架(python单机版自动化测试框架源代码),所以自己用javascript写了一个录制工具,在控制台打印记录的python脚本如下:

 

代码如下(初稿,还在不断调试完善中):

  1. var click_textContent = '
  2. var father_level = 0;
  3. var child_ctl = "";
  4. var child_ctl_tmp = "";
  5. var next_focusedElement = null;
  6. window.clickedElement = null;
  7. document.addEventListener("click", function(event) {
  8. window.clickedElement = event.target;
  9. console.log(window.clickedElement);
  10. father_level = 0;
  11. myDispose_click(window.clickedElement);
  12. });
  13. function myDispose_click(focusedElement) {
  14. console.log(`开始 父${father_level} -------------------------`);
  15. let tag_name = focusedElement.tagName.toLowerCase();
  16. let outerHTML = focusedElement.outerHTML;
  17. console.log(outerHTML);
  18. if (tag_name === "body") {
  19. let xpath = getElementfullXPath(next_focusedElement);
  20. let elements = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  21. if (elements && elements.snapshotLength === 1) {
  22. console.log(`self.myWtClickEx(driver, By.XPATH, "${xpath}")`);
  23. console.log("结束:tag名称为body");
  24. console.log(`结束 父${father_level} -------------------------`);
  25. return xpath;
  26. } else {
  27. console.log("结束:tag名称为body");
  28. console.log(`结束 父${father_level} -------------------------`);
  29. return null;
  30. }
  31. }
  32. let my_all_value = "";
  33. let text = focusedElement.textContent.trim().replace(/"/g, "\\\"");
  34. if (text !== "" && !text.includes("\\n")) {
  35. my_all_value = `contains(text(),\'${text}\')`;
  36. if (myDispose_count_number(text, "text", tag_name)) {
  37. let xpath = `//${tag_name}[${my_all_value}]`;
  38. let parameter = `driver, By.XPATH, "${xpath}"`;
  39. myDispose_success(parameter);
  40. return parameter;
  41. }
  42. } else {
  43. text = ""
  44. }
  45. let attributes = focusedElement.attributes;
  46. console.log(`属性名称列表: ${Array.from(attributes).map(attr => attr.name).join(",")}`);
  47. for (let i = 0; i < attributes.length; i++) {
  48. let attribute_name = attributes[i].name;
  49. let attribute_value = attributes[i].value;
  50. if (attribute_name === "class") {
  51. let class_value_list = attribute_value.split(" ");
  52. console.log(`class列表:${class_value_list}`);
  53. if (class_value_list.includes("focusing")) {
  54. class_value_list = class_value_list.filter(value => value !== "focusing");
  55. }
  56. for (let class_value of class_value_list) {
  57. if (my_all_value === "") {
  58. my_all_value = `contains(@class,"${class_value}")`;
  59. } else {
  60. my_all_value += ` and contains(@class,"${class_value}")`;
  61. }
  62. if (myDispose_count_number(class_value, attribute_name, tag_name)) {
  63. let parameter = `driver, By.CLASS_NAME, "${class_value}"`;
  64. myDispose_success(parameter);
  65. return parameter;
  66. }
  67. let xpath = "";
  68. if (text === "") {
  69. xpath = `//${tag_name}[${my_all_value}]`;
  70. } else {
  71. xpath = `//${tag_name}[contains(text(),\'${text}\') and ${my_all_value}]`;
  72. }
  73. let result = myDispose_count_evaluate(xpath);
  74. if (result) {
  75. let parameter = `driver, By.XPATH, "${xpath}"`;
  76. myDispose_success(parameter);
  77. return parameter;
  78. }
  79. }
  80. } else {
  81. /*if (attribute_value === "" || /\d/.test(attribute_value)) {*/
  82. if (attribute_value === "" || (attribute_name !== "src" && attribute_value.match(/[0-9]/))) {
  83. continue;
  84. }
  85. if (my_all_value === "") {
  86. my_all_value = `contains(@${attribute_name}, "${attribute_value}")`;
  87. } else {
  88. my_all_value += ` and contains(@${attribute_name}, "${attribute_value}")`;
  89. }
  90. if (myDispose_count_number(attribute_value, attribute_name, tag_name)) {
  91. let xpath = `//${tag_name}[contains(@${attribute_name}, "${attribute_value}")]`;
  92. let parameter = `driver, By.XPATH, "${xpath}"`;
  93. myDispose_success(parameter);
  94. return parameter;
  95. }
  96. let xpath = "";
  97. if (text === "") {
  98. xpath = `//${tag_name}[${my_all_value}]`;
  99. } else {
  100. xpath = `//${tag_name}[contains(text(),\'${text}\') and ${my_all_value}]`;
  101. }
  102. let result = myDispose_count_evaluate(xpath);
  103. if (result) {
  104. let parameter = `driver, By.XPATH, "${xpath}"`;
  105. myDispose_success(parameter);
  106. return parameter;
  107. }
  108. }
  109. }
  110. if (my_all_value !== "") {
  111. let xpath = `//${tag_name}[${my_all_value}]`;
  112. let result = myDispose_count_evaluate(xpath);
  113. if (result) {
  114. let parameter = `driver, By.XPATH, "${xpath}"`;
  115. myDispose_success(parameter);
  116. return parameter;
  117. } else {
  118. let textStr = `self.myWtClickEx(driver, By.XPATH, "${xpath}")`;
  119. console.log("# 不是1");
  120. console.log(textStr);
  121. console.log(`结束 父${father_level} -------------------------`);
  122. if (father_level === 0) {
  123. child_ctl = `father, By.XPATH, ".${xpath}"`;
  124. child_ctl_tmp = `.${xpath}`;
  125. next_focusedElement = focusedElement;
  126. }
  127. let father = focusedElement.parentElement;
  128. if (father) {
  129. father_level++;
  130. myDispose_click(father);
  131. }
  132. }
  133. }
  134. return null;
  135. }
  136. function myDispose_success(parameter) {
  137. if (father_level === 0) {
  138. console.log(`self.myWtClickEx(${parameter})`);
  139. } else {
  140. console.log(`father = self.myWtFindElement(${parameter})`);
  141. console.log(`self.myWtClickEx(${child_ctl})`);
  142. }
  143. console.log(`结束 父${father_level} -------------------------`);
  144. }
  145. function myDispose_count_evaluate(xpath) {
  146. let elements = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  147. if (father_level === 0) {
  148. if (elements.snapshotLength === 1) {
  149. return true
  150. } else {
  151. return null
  152. }
  153. } else {
  154. if (elements.snapshotLength === 1) {
  155. let firstElement = elements.snapshotItem(0);
  156. let result = document.evaluate(child_ctl_tmp, firstElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  157. if (result.snapshotLength === 1) {
  158. return true
  159. } else {
  160. return null
  161. }
  162. } else {
  163. return null
  164. }
  165. }
  166. }
  167. function myDispose_count_number(attribute_value, attribute_name, tag_name) {
  168. if (attribute_value === "") {
  169. return null;
  170. };
  171. if (attribute_name !== "text" && attribute_name !== "src" && attribute_value.match(/[0-9]/)) {
  172. return null;
  173. };
  174. let xpath;
  175. if (attribute_name !== "text") {
  176. xpath = `//${tag_name}[contains(@${attribute_name}, "${attribute_value}")]`;
  177. } else {
  178. xpath = `//${tag_name}[contains(text(), \'${attribute_value}\')]`;
  179. };
  180. let result = myDispose_count_evaluate(xpath);
  181. if (result) {
  182. console.log(`${attribute_name}:"${attribute_value}" 在网页中出现1次`);
  183. return true;
  184. } else {
  185. console.log(`${attribute_name}:"${attribute_value}" 在网页中出现了多次`);
  186. return null;
  187. };
  188. }
  189. function getElementfullXPath(element) {
  190. if (element && element.id)
  191. if (!element.id.match(/[0-9]/)) {
  192. return \'//*[@id="\' + element.id + \'"]\';
  193. }
  194. if (element==null)
  195. return "";
  196. var index = 0;
  197. var loacl_tagName = element.tagName;
  198. var sibling = element.previousSibling;
  199. var sibling_tagName = null;
  200. if (sibling) {
  201. sibling_tagName = sibling.tagName;
  202. }
  203. while (sibling && sibling.nodeType === 1 && loacl_tagName === sibling_tagName) {
  204. index++;
  205. sibling = sibling.previousSibling;
  206. if (sibling) {
  207. sibling_tagName = sibling.tagName;
  208. } else {
  209. sibling_tagName = null;
  210. }
  211. }
  212. parent = element.parentNode;
  213. if (parent) {
  214. var xpath = getElementfullXPath(parent);
  215. if (xpath === "undefined") {
  216. return "";
  217. } else {
  218. if (index === 0) {
  219. xpath += "/" + element.tagName.toLowerCase();
  220. } else {
  221. xpath += "/" + element.tagName.toLowerCase() + "[" + (index+1) + "]";
  222. }
  223. return xpath;
  224. }
  225. } else {
  226. return "";
  227. }
  228. }
  229. ';
  230. var input_textContent = '
  231. let inputs = document.querySelectorAll(`input[type="text"]`);
  232. inputs.forEach(input => {
  233. input.addEventListener("input", function(event) {
  234. console.log(this.value);
  235. let parameter = myDispose_click(event.target);
  236. if (parameter !== null) {
  237. let textStr = `self.myWtSendKeysWebEx(${parameter}, "${this.value}")`;
  238. console.log(textStr);
  239. }
  240. });
  241. });
  242. ';
  243. /*iframe*/
  244. let iframes = document.getElementsByTagName('iframe');
  245. for (let i = 0; i < iframes.length; i++) {
  246. let iframe = iframes[i];
  247. if (iframe.contentWindow && iframe.contentWindow.document) {
  248. let script = iframe.contentWindow.document.createElement('script');
  249. script.type = 'text/javascript';
  250. script.textContent = click_textContent;
  251. iframe.contentWindow.document.head.appendChild(script);
  252. let inputs = iframe.contentWindow.document.querySelectorAll(`input[type="text"]`);
  253. inputs.forEach(input => {
  254. input.addEventListener("input", function(event) {
  255. console.log(this.value);
  256. let parameter = myDispose_click(event.target);
  257. if (parameter !== null) {
  258. let textStr = `self.myWtSendKeysWebEx(${parameter}, "${this.value}")`;
  259. console.log(textStr);
  260. }
  261. });
  262. });
  263. }
  264. }
  265. /*非iframe*/
  266. let script = document.createElement('script');
  267. script.type = 'text/javascript';
  268. script.textContent = click_textContent + input_textContent;
  269. document.head.appendChild(script);

 

原文链接:https://www.cnblogs.com/rmticocean/p/18329662

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号