我有一个目前在不同开发环境中运行的测试套件。最近完成了对应用程序的完全重写。部署到新环境。
该应用程序看起来&行为几乎相同。页面逻辑或多或少相同。最重要的区别是HTML重写使我的定位器无用。我不确定如何处理这个新环境的定位器,同时坚持页面对象模型。
页面对象模型声明所有页面逻辑应保存在相应的页面对象类中。我假设这也包括定位器。
遵循这个策略会让我看到一个充满重复定位器的膨胀页面对象类。是否有任何建议的最佳实践或清洁解决方案来解决这个问题?
我能想到的可能解决方案是:
可以评论这些解决方案听起来不错吗?或提供任何其他建议?
答案 0 :(得分:3)
肯定会将pageobject类之外的定位器移动到两个不同的类中,一个用于旧定位器,另一个用于新定位器。对每个定位器使用public static final String。您将遇到的问题是Java注释值需要常量表达式,因此您不能使用方法将不同的定位器发送到FindBy。但是您可以使用三元运算符来创建常量表达式。
下面我添加了基于全局标志的代码,单击来自单个WebElement的不同按钮,但定位器由FindBy注释的“using”值上的表达式更改。从属性文件初始化驱动程序时,可以在启动时设置全局标志的值。
这是您需要包含在发现给findElement()的FindBy和定位器中的内容 - using = GlobalFlag.devEnv? NewLocators.newLocxpath:OldLocators.newLocxpath 。在任何地方复制粘贴都会很痛苦。
您可以在网站公开的情况下试用代码。
class CartConstant {
//Old locators
public static final String cartxpath = "//span[.='Cart']";
}
class AccountConstant {
//New locators
public static final String accxpath = "//span[.='Account']";
}
class GlobalFlag {
//Initialize this at the start
public static final boolean devEnv = true;
}
public class ChangeAnnotation {
//Change this in the code to include the choice
@FindBy(how=How.XPATH, using=GlobalFlag.devEnv ? AccountConstant.accxpath : CartConstant.cartxpath)
private WebElement butt;
@Test
public void demoSQA() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "E:/Software Testing/Selenium/Jars/chromedriver.exe");
ChromeOptions chop = new ChromeOptions();
chop.addArguments("test-type");
chop.addArguments("start-maximized");
WebDriver driver = new ChromeDriver(chop);
driver.get("http://store.demoqa.com/products-page/product-category/imacs/");
Thread.sleep(3000);
PageFactory.initElements(driver, this);
butt.click();
}
}
答案 1 :(得分:0)
这就是我设法克服这个问题的方法。
我为不同的环境保留了不同的元素属性文件。
让我们说环境A,B 在我的项目中,我保留了两个名为Elements_A.properties和Elements_B.properties的属性文件 这些属性文件包含所有页面元素。 如果一个元素与另一个元素不同,则不会出现问题,因为根据环境运行脚本时,您可以在脚本中引用相关的属性文件。
让我们说 在HomePage的A和B中,有一个带有不同定位器的文本框。
所以在属性文件A中我们可以提到元素为 HomePage_Name_TextBox = id_NameInA “id_NameInA”是定位符值,“HomePage_Name_TextBox”是您将用于引用该特定元素的字符串。
在属性文件A中,我们可以提及相同的元素 HomePage_Name_TextBox = id_NameInB “id_NameInB”是定位符值,“HomePage_Name_TextBox”是您将用于引用该特定元素的字符串。
您可以注意到两个元素的名称相同( HomePage_Name_TextBox ),定位器值不同。
在每个页面类中,我都声明了一个Map,现在您有几个选项可以决定如何初始化页面的元素。
public class HomePage {
Map<String, String> elementsMap = new HashMap<String, String>();
//Option 1
public HomePage(Map<String, String> elementMapObj) {
elementsMap = elementMapObj;
}
//Option 2
public HomePage() {
Properties prop = new Properties();
FileReader reader;
HashMap<String, String> propertyMap = new HashMap<String, String>();
try {
reader = new FileReader(new File("CommonConfig.properties"));
prop.load(reader);
for (String key : prop.stringPropertyNames())
{
String value = prop.getProperty(key);
propertyMap.put(key, value);
}
} catch (Exception e) {
//System.out.println(e.toString());
}
try {
reader = new FileReader(new File(propertyMap.get("ElementPropFilePath")));
prop.load(reader);
for (String key : prop.stringPropertyNames())
{
String value = prop.getProperty(key);
elementsMap.put(key, value);
}
} catch (Exception e) {
//System.out.println(e.toString());
}
}
}
如果要在A中运行脚本,可以在运行之前将公共属性文件中的“ElementPropFilePath”更改为“Resources / Elements_A.properties”。 如果要在B中运行脚本,可以在运行之前将公共属性文件中的“ElementPropFilePath”更改为“Resources / Elements_B.properties”(这是文件在计算机中的位置)。
简单地说,如果您维护包含每个环境的所有元素的属性文件,并提供该属性详细信息并填充您在每个页面类中的elementMap,那么您将能够使用公共字符串引用该元素您用于两个环境(在此示例中为HomePage_Name_TextBox)