【问题标题】:Find if the Layout has particular text view or not查找布局是否具有特定的文本视图
【发布时间】:2016-01-09 04:53:57
【问题描述】:

我有这样的线性布局:

现在有些线性布局有子类别,有些没有。类似地,有些有折扣,同样没有。

所以当我做这样的事情时:

List<WebElement> allFieldsInLayout = driver.findElements(By.id("com.flipkart.android:id/product_list_product_item_layout"));
List<WebElement> allTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_main_text']"));
List<WebElement> allsubTitlesOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_sub_text']"));
List<WebElement> allOfferPricesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_price']"));
List<WebElement> allListPriceOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_mrp']"));

然后尝试在其中打印文本:

for(int i=0;i<allTitlesOnCurrentScreen.size();i++){

        System.out.println("TITLE : "+allTitlesOnCurrentScreen.get(i).getAttribute("text")
                        + "SUB TITLE : "+allsubTitlesOnCurrentScreen.get(i).getAttribute("text")
                        + "OFFER PRICE : "+allOfferPricesOnCurrentScreen.get(i).getAttribute("text")
                        + "LIST PRICE : "+allListPriceOnCurrentScreen.get(i).getAttribute("text")
        );
    }

我得到了 Array Out of Bound 异常。所以我想是否有可能从这个列表的外部布局中获取所有子字段的资源 ID。我试过这样:

for(int i=0;i<allFieldsInLayout.size();i++){
            List<WebElement> allElementsinCurrentLayout = allFieldsInLayout.get(i).findElements(By.xpath("//android.widget.RelativeLayout[@index='2']"));
            for(int j=0;j<allElementsinCurrentLayout.size();j++) {
                System.out.println("Layout " + allElementsinCurrentLayout.get(j));
            }
}

但它给出了例外

Cannot use xpath locator strategy from an element. It can only be used from the root element)

如果我没有相应的子标题或没有折扣,我希望在我的列表中为 NULL。怎么办?

【问题讨论】:

  • 为什么要使用这种方法来查找每一项?通过 ID(或名称、标签等)查找每个项目可能更容易,如果您在此处查找,它可以找到不同的方法。
  • @GastonF。你说的是哪种方法?
  • Here 有使用 findViewById 的示例。 Here 按资源名称查找。 Here其他方法。
  • @GastonF。我正在使用 Appium 框架
  • 好的,我在您的代码中发现了一个问题,您正在迭代 allTitlesOnCurrentScreen 但尝试获取具有相同索引的值 allListPriceOnCurrentScreen,也许您的代码应该类似于 this

标签: android selenium appium selendroid


【解决方案1】:

一般来说,我处理此类问题的方法是找到包含单个产品的所有产品信息的最顶层元素。将这些元素作为集合返回并遍历它。在每次迭代中,查找包含元素的不同信息...检查是否存在并获取数据(如果存在)。此方法将允许您将每个产品的所有属性/数据整齐地捕获为一个包。

您的方法的问题是您正在存储数据元素,例如字幕,与产品分开。所以,想象一下如果你的页面上有 4 个产品,其中只有 2 个有字幕。您循环访问字幕的 4 个产品(按索引)...您将遇到 2 个问题:1)您将跑出字幕数组的末尾,因为只有 2 个并且您正在循环到 4 个。2)您的字幕数组与产品数组中的产品不匹配。

想象这是你的页面

Product1
Subtitle1

Product2

Product3
Subtitle3

Product4

您的产品数组将包含:Product1、Product2、Product3、Product4

您的字幕数组将包含:Subtitle1、Subtitle3

所以当你循环使用产品索引时,你会得到:

Product1, Subtitle1
Product2, Subtitle3 // notice the mismatch 2 and 3
Product3, Array out of index error

所以您用完了字幕数组的末尾,而您的字幕与相应的产品不匹配。希望这个例子更有意义......

无论如何,这就是我的做法。我没有移动应用程序,所以我去了flipkart.com 并搜索了翻盖并编写了下面的代码来演示我在说什么。此代码有效,我刚刚运行它。

public static void main(String[] args)
{
    WebDriver driver = new FirefoxDriver();
    driver.manage().window().maximize();
    driver.get("http://www.flipkart.com/search?q=flip+cover&as=on&as-show=on&otracker=start&as-pos=4_q_flip+cover&sid=search.flipkart.com&storePath=search.flipkart.com&type=pr&redirectToResponseURL=false&redirection=true&isMsiteTraffic=1");
    List<Product> products = new ArrayList<>(); // List of Product type that will contain each product on the page
    List<WebElement> productContainers = driver.findElements(By.cssSelector("div.gd-col.gu3")); // the outermost element that contains all data related to a given product
    // loop through the product container elements and extract each bit of data that we care about
    for (WebElement productContainer : productContainers)
    {
        String name = productContainer.findElement(By.cssSelector("a[data-tracking-id='prd_title']")).getText().trim();
        String ratingStars = ""; // we have to initialize these variables at this scope so we can access them later outside the IF below
        String NoOfRatings = ""; // NOTE: if a rating does not exist for this product, ratingStars and NoOfRatings will be empty string, ""
        // these next two lines are how we determine if a piece of data exists... get the element using .findElements...
        List<WebElement> ratingContainer = productContainer.findElements(By.cssSelector("div.pu-rating"));
        // ... and then check to see if the list is empty
        if (!ratingContainer.isEmpty())
        {
            // ratings exist for this product, grab the relevant data
            WebElement rating = ratingContainer.get(0).findElement(By.cssSelector("div.fk-stars-small"));
            ratingStars = rating.getAttribute("title"); // product rating in stars
            NoOfRatings = ratingContainer.get(0).getText().trim(); // the total number of ratings, you can parse this string and extract the number, if desired
        }
        String finalPrice = productContainer.findElement(By.cssSelector("div.pu-final")).getText().trim(); // the price, you can extract the number, if desired
        products.add(new Product(name, finalPrice, ratingStars, NoOfRatings)); // add all the relevant data into a nice, neat package just for this one product
    }

    // dumps the data for the products on the page
    for (Product product : products)
    {
        System.out.println("Product: " + product.name);
        System.out.println("Rating: " + product.ratingStars);
        System.out.println("Number of ratings: " + product.NoOfRatings);
        System.out.println("Final price: " + product.finalPrice);
        System.out.println("-----------------------------");
    }
}

// this class holds just 4 bits of data for each product, you can obviously add more to the class if you want to store more data
public static class Product
{
    public String name;
    public String finalPrice;
    public String ratingStars;
    public String NoOfRatings;

    public Product(String name, String finalPrice, String ratingStars, String NoOfRatings)
    {
        this.name = name;
        this.finalPrice = finalPrice;
        this.ratingStars = ratingStars;
        this.NoOfRatings = NoOfRatings;
    }
}

输出看起来像

-----------------------------
Product: KolorEdge Flip Cover for Lenovo A6000 Plus (Black)
Rating: 3 stars
Number of ratings: (26 ratings)
Final price: Rs. 160
-----------------------------
Product: Jeelo Flip Cover for Motorola Moto G 2nd Generation (Bl...
Rating: 3 stars
Number of ratings: (128 ratings)
Final price: Rs. 137
-----------------------------
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-04
    • 2016-10-06
    • 2015-03-24
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多