51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 2043|回复: 1
打印 上一主题 下一主题

[讨论] web 自动化测试框架的一些想法和实践

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-2-28 16:26:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近用java在写自动化测试框架,写着写着有点感觉好繁复。所以写出来希望可以得到一些建议,
以下主要针对的是网页测试,总体的想法是:
1. Page Object模式,页面元素和外面的测试数据的模型命名一样,这样省去一些对应的代码,里
面自己分装了自定义的元素
2. 使用类似于爬虫的第三方包生成page object 模型
3. 通过操作流程直接生成测试代码
4. 使用testng,data provider 来驱动测试

以下是一些实现:

使用一下脚本解析页面元素,source.txt是页面的html源码,可以页面片段也可以是整个页面:
  1. PageObjectParser poParser = PageObjectParser.buildFromFilePath("source.txt");
  2. poParser.parseRadio();
  3. poParser.parseInputBox("ng-model");
复制代码
得到一下结果:
  1. @ElementName(elementName="property.propertyUsage")
  2. private Radio propertyUsage;
  3. @FindBy(name="property.estateName")
  4. @ElementName(elementName = "property.estateName")
  5. private InputBox estateName;
  6. @FindBy(name="property.address")
  7. @ElementName(elementName = "property.address")
  8. private InputBox address;
  9. @FindBy(name="property.roomNo")
  10. @ElementName(elementName = "property.roomNo")
  11. private InputBox roomNo;
  12. @FindBy(name="property.permitNo")
  13. @ElementName(elementName = "property.permitNo")
  14. private InputBox permitNo;
复制代码
稍微复杂点的页面:
  1. PageObjectParser poParser = PageObjectParser.buildFromFilePath("source.txt");
  2.         poParser.parseRadio();
  3.         poParser.parseInputBoxInTable("ng-model");
  4.         poParser.parseSelect("div");
复制代码
得到结果:
  1. @FindBy(name="property_propertySource")
  2. @ElementName(elementName="property.propertySource")
  3. private Radio propertySource;
  4. @FindBy(name="property_status")
  5. @ElementName(elementName="property.status")
  6. private Radio status;
  7. @FindBy(name="property_shape")
  8. @ElementName(elementName="property.shape")
  9. private Radio shape;
  10. @FindBy(name="property_currentStatus")
  11. @ElementName(elementName="property.currentStatus")
  12. private Radio currentStatus;
  13. @FindBy(name="property_propertyLook")
  14. @ElementName(elementName="property.propertyLook")
  15. private Radio propertyLook;
  16. @FindBy(name="property_isAuction")
  17. @ElementName(elementName="property.isAuction")
  18. private Radio isAuction;
  19. @FindBy(name="property_flagLoan")
  20. @ElementName(elementName="property.flagLoan")
  21. private Radio flagLoan;
  22. @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_contactName']")
  23. @ElementName(elementName="property.contactName")
  24. private InputBox contactName;
  25. @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_floorAll']")
  26. @ElementName(elementName="property.floorAll")
  27. private InputBox floorAll;
  28. @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_floorHeight']")
  29. @ElementName(elementName="property.floorHeight")
  30. private InputBox floorHeight;
  31. @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//select[@name='property_relationship']")
  32. @ElementName(elementName="property.relationship")
  33. private SelectList relationship;

  34. 生成页面模型之后,生成一个页面元素描述的excel,可以是多个页面:

  35. WebUICodeGenerator.build().writePageObjectsToExcel("sample.xls",
  36.                 Lists.newArrayList(MockPage1.class,MockPage2.class));
复制代码

给业务流程自定需要跑那些元素,标上顺序,使用代码生成一个流程的方法或者注解:
2. 自动生成annotation 或者测试代码

当整个业务流程涉及的页面完成后,使用如下的代码生成一份excel:
  1. WebUICodeGenerator t=  WebUICodeGenerator.build("AddProperty.xls");
  2.                 t.generateAnnotationStatement("流程1");
  3.         t.generateAnnotationStatement("流程12");

  4. 注解或者代码:得到注解

  5. MockPage1:
  6. @UIActions(actions={@UIAction(processName="流程1",elementActionDescription={"propertyUsage","estateName","address","roomNo"})
  7. })
  8. MockPage2:
  9. @UIActions(actions={@UIAction(processName="流程1",elementActionDescription={"contactName","floorAll","isAuction","currentStatus","status","propertyDecoration"})
  10. })


  11. 放到页面Page Object类去。编写流程类:

  12. 最后构建整个业务流程,使用如下代码:中文命名只是为了说明使用。

  13. public class 流程1 extends BaseWebTestAction {

  14.     public 流程1(WebDriver driver, TestData testData) {
  15.         super(driver, testData);
  16.     }

  17.     @Override
  18.     public void execute() {
  19.         WebTestActionBuilder.createTestActionByUIAction(MockPage1.class, "流程1",driver, testData).execute();
  20.         WebTestActionBuilder.createTestActionByUIAction(MockPage2.class, "流程1",driver, testData).execute();
  21.     }
  22. }

  23. 以上代码中execute()实质上等价:

  24.    MockPage1 page1 = ModifiedPageFactory.createPageObject(driver,MockPage1.class);
  25.         page1.processUIAction("流程1",testData);
  26.         MockPage2 page2 = ModifiedPageFactory.createPageObject(driver,MockPage2.class);
  27.         page2.processUIAction("流程1",testData);

  28. 或者:

  29.    MockPage1 page1 = ModifiedPageFactory.createPageObject(driver,MockPage1.class);
  30.         page1.getPropertyUsage().selectByVisibleText(testData.get("propertyUsage"));
  31.         page1.getAddress().input(testData.get("address"));
  32.         page1.getEstateName().input(testData.get("estateName"));
  33.         page1.getRoomNo().input(testData.get("roomNo"));
  34.         MockPage2 page2 = ModifiedPageFactory.createPageObject(driver,MockPage2.class);
  35.         page2.getContactName().input(testData.get("contractName"));
  36.         ...........

  37. 如果不生成注解,直接生成代码就是:
  38. 使用代码:

  39.   WebUICodeGenerator.build("AddProperty.xls").generateSingleTestStep("流程1");

  40. 生成流程的函数:

  41. public static void 流程1(WebDriver driver,TestData testData){
  42. WebTestActionBuilder.createTestActionByElementActionList(MockPage1.class,Lists.newArrayList("propertyUsage","estateName","address","roomNo"),driver,testData).execute();
  43. WebTestActionBuilder.createTestActionByElementActionList(MockPage2.class,Lists.newArrayList("contactName","floorAll","isAuction","currentStatus","status","propertyDecoration"),driver,testData).execute();
  44. }
复制代码
3. 测试数据准备

测试离不开测试数据的准备,测试数据类可以直接页面Page Object来生成:
  1. WebUICodeGenerator t=  WebUICodeGenerator.build();
  2.         t.generateTestDataClass(Lists.newArrayList(MockPage1.class,MockPage2.class));

  3. 结果:

  4. private String roomNo;
  5. private String permitNo;
  6. private String propertySource;
  7. private String status;
  8. private String shape;
  9. private String currentStatus;
  10. private String propertyLook;
  11. ..........

  12. 使用testng 驱动测试

  13. public class SampleTest extends BaseWebTest {

  14.     @DataProvider(name = "sample_data")
  15.     public Iterator<Object[]> getAPITestData(Method m) throws Exception{
  16.         Map<String, Class> clazzMap = new HashMap<String, Class>();
  17.         clazzMap.put("Sample", Sample.class);
  18.         Iterator<Object[]> y = ExcelHelper.build("abc.xls").ToIteratorInColMode(clazzMap);
  19.         return y;
  20.     }

  21.     @Test(dataProvider ="property_data" )
  22.     public void addProperty(Sample testData) {
  23.        Login。。。。。
  24.         流程1 flow = new 流程1(driver,testData);
  25.         flow.execute();
  26.     }

  27. }
复制代码
大概的思路是这样的。请大家多提宝贵意见。在这个过程可能可能看不到一些webdriver的操作,这个
操作主要是封装了一层对应关系,每个自定义元素都有一个默认操作,没有特别说明就使用默认的操作。

其中对于自定义的元素也是使用过了PageFactory的方式,参考selenium的实现,自己做了一些定制化。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-25 04:19 , Processed in 0.069802 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表