|
最近用java在写自动化测试框架,写着写着有点感觉好繁复。所以写出来希望可以得到一些建议,
以下主要针对的是网页测试,总体的想法是:
1. Page Object模式,页面元素和外面的测试数据的模型命名一样,这样省去一些对应的代码,里
面自己分装了自定义的元素
2. 使用类似于爬虫的第三方包生成page object 模型
3. 通过操作流程直接生成测试代码
4. 使用testng,data provider 来驱动测试
以下是一些实现:
使用一下脚本解析页面元素,source.txt是页面的html源码,可以页面片段也可以是整个页面:
- PageObjectParser poParser = PageObjectParser.buildFromFilePath("source.txt");
- poParser.parseRadio();
- poParser.parseInputBox("ng-model");
复制代码 得到一下结果:
- @ElementName(elementName="property.propertyUsage")
- private Radio propertyUsage;
- @FindBy(name="property.estateName")
- @ElementName(elementName = "property.estateName")
- private InputBox estateName;
- @FindBy(name="property.address")
- @ElementName(elementName = "property.address")
- private InputBox address;
- @FindBy(name="property.roomNo")
- @ElementName(elementName = "property.roomNo")
- private InputBox roomNo;
- @FindBy(name="property.permitNo")
- @ElementName(elementName = "property.permitNo")
- private InputBox permitNo;
复制代码 稍微复杂点的页面:
- PageObjectParser poParser = PageObjectParser.buildFromFilePath("source.txt");
- poParser.parseRadio();
- poParser.parseInputBoxInTable("ng-model");
- poParser.parseSelect("div");
复制代码 得到结果:
- @FindBy(name="property_propertySource")
- @ElementName(elementName="property.propertySource")
- private Radio propertySource;
- @FindBy(name="property_status")
- @ElementName(elementName="property.status")
- private Radio status;
- @FindBy(name="property_shape")
- @ElementName(elementName="property.shape")
- private Radio shape;
- @FindBy(name="property_currentStatus")
- @ElementName(elementName="property.currentStatus")
- private Radio currentStatus;
- @FindBy(name="property_propertyLook")
- @ElementName(elementName="property.propertyLook")
- private Radio propertyLook;
- @FindBy(name="property_isAuction")
- @ElementName(elementName="property.isAuction")
- private Radio isAuction;
- @FindBy(name="property_flagLoan")
- @ElementName(elementName="property.flagLoan")
- private Radio flagLoan;
- @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_contactName']")
- @ElementName(elementName="property.contactName")
- private InputBox contactName;
- @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_floorAll']")
- @ElementName(elementName="property.floorAll")
- private InputBox floorAll;
- @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//input[@name='property_floorHeight']")
- @ElementName(elementName="property.floorHeight")
- private InputBox floorHeight;
- @FindBy(xpath="//tr[not(contains(@style,'display: none'))]//select[@name='property_relationship']")
- @ElementName(elementName="property.relationship")
- private SelectList relationship;
- 生成页面模型之后,生成一个页面元素描述的excel,可以是多个页面:
- WebUICodeGenerator.build().writePageObjectsToExcel("sample.xls",
- Lists.newArrayList(MockPage1.class,MockPage2.class));
复制代码
给业务流程自定需要跑那些元素,标上顺序,使用代码生成一个流程的方法或者注解:
2. 自动生成annotation 或者测试代码
当整个业务流程涉及的页面完成后,使用如下的代码生成一份excel:
- WebUICodeGenerator t= WebUICodeGenerator.build("AddProperty.xls");
- t.generateAnnotationStatement("流程1");
- t.generateAnnotationStatement("流程12");
- 注解或者代码:得到注解
- MockPage1:
- @UIActions(actions={@UIAction(processName="流程1",elementActionDescription={"propertyUsage","estateName","address","roomNo"})
- })
- MockPage2:
- @UIActions(actions={@UIAction(processName="流程1",elementActionDescription={"contactName","floorAll","isAuction","currentStatus","status","propertyDecoration"})
- })
- 放到页面Page Object类去。编写流程类:
- 最后构建整个业务流程,使用如下代码:中文命名只是为了说明使用。
- public class 流程1 extends BaseWebTestAction {
- public 流程1(WebDriver driver, TestData testData) {
- super(driver, testData);
- }
- @Override
- public void execute() {
- WebTestActionBuilder.createTestActionByUIAction(MockPage1.class, "流程1",driver, testData).execute();
- WebTestActionBuilder.createTestActionByUIAction(MockPage2.class, "流程1",driver, testData).execute();
- }
- }
- 以上代码中execute()实质上等价:
- MockPage1 page1 = ModifiedPageFactory.createPageObject(driver,MockPage1.class);
- page1.processUIAction("流程1",testData);
- MockPage2 page2 = ModifiedPageFactory.createPageObject(driver,MockPage2.class);
- page2.processUIAction("流程1",testData);
- 或者:
- MockPage1 page1 = ModifiedPageFactory.createPageObject(driver,MockPage1.class);
- page1.getPropertyUsage().selectByVisibleText(testData.get("propertyUsage"));
- page1.getAddress().input(testData.get("address"));
- page1.getEstateName().input(testData.get("estateName"));
- page1.getRoomNo().input(testData.get("roomNo"));
- MockPage2 page2 = ModifiedPageFactory.createPageObject(driver,MockPage2.class);
- page2.getContactName().input(testData.get("contractName"));
- ...........
- 如果不生成注解,直接生成代码就是:
- 使用代码:
- WebUICodeGenerator.build("AddProperty.xls").generateSingleTestStep("流程1");
- 生成流程的函数:
- public static void 流程1(WebDriver driver,TestData testData){
- WebTestActionBuilder.createTestActionByElementActionList(MockPage1.class,Lists.newArrayList("propertyUsage","estateName","address","roomNo"),driver,testData).execute();
- WebTestActionBuilder.createTestActionByElementActionList(MockPage2.class,Lists.newArrayList("contactName","floorAll","isAuction","currentStatus","status","propertyDecoration"),driver,testData).execute();
- }
复制代码 3. 测试数据准备
测试离不开测试数据的准备,测试数据类可以直接页面Page Object来生成:
- WebUICodeGenerator t= WebUICodeGenerator.build();
- t.generateTestDataClass(Lists.newArrayList(MockPage1.class,MockPage2.class));
- 结果:
- private String roomNo;
- private String permitNo;
- private String propertySource;
- private String status;
- private String shape;
- private String currentStatus;
- private String propertyLook;
- ..........
- 使用testng 驱动测试
- public class SampleTest extends BaseWebTest {
- @DataProvider(name = "sample_data")
- public Iterator<Object[]> getAPITestData(Method m) throws Exception{
- Map<String, Class> clazzMap = new HashMap<String, Class>();
- clazzMap.put("Sample", Sample.class);
- Iterator<Object[]> y = ExcelHelper.build("abc.xls").ToIteratorInColMode(clazzMap);
- return y;
- }
- @Test(dataProvider ="property_data" )
- public void addProperty(Sample testData) {
- Login。。。。。
- 流程1 flow = new 流程1(driver,testData);
- flow.execute();
- }
- }
复制代码 大概的思路是这样的。请大家多提宝贵意见。在这个过程可能可能看不到一些webdriver的操作,这个
操作主要是封装了一层对应关系,每个自定义元素都有一个默认操作,没有特别说明就使用默认的操作。
其中对于自定义的元素也是使用过了PageFactory的方式,参考selenium的实现,自己做了一些定制化。
|
|