2

I have an IF-AND statement that isn't operating properly. This is occurring on Python 2.7.9.

    numberOfActiveConfigs = len(driver.find_elements_by_xpath("//select[@id='active_config']/option"))
    for cnt in range (0, 5):
        print "Count: ", cnt
        temp = len(driver.find_elements_by_xpath("//select[@id='active_config']/option"))
        print type(numberOfActiveConfigs)
        if numberOfActiveConfigs > 3:
            cnt = cnt + 1
        else:
            numberOfActiveConfigs = temp
            cnt = 0
    print "Number of Configs: ", numberOfActiveConfigs

Basically, the code stores the number of elements in a table & then checks to see if the number of elements is greater than 3. If it is, then it increments count until it reaches '5' and stops. The print statements are for debugging.

For some reason, the 'if' statement keeps coming back as TRUE despite the fact that the count is equal to '2'.

Print out:
Count:  0
<type 'int'>
Count:  1
<type 'int'>
Count:  2
<type 'int'>
Count:  3
<type 'int'>
Count:  4
<type 'int'>
Number of Configs:  2

As you can also see, value 'numberOfActiveConfigs' is of type 'int', so this isn't a case where I'm comparing a string to an int. I have no clue why this is happening & have a feeling this is going to be a silly mistake on my behalf.

rwbyrd
  • 416
  • 5
  • 24
  • 1
    Why do you need to get the options 5 times in a row? – alecxe Aug 03 '15 at 19:56
  • 1
    `numberOfActiveConfigs` is set outside of your `for` loop. You are always comparing the same value to see if it's `> 3` – AlG Aug 03 '15 at 19:58
  • I'm making sure the table has been at least partially loaded before I continue with my testing. I need at least 3 objects to be listed in the table to confirm a test I'm doing. This helps me when running the same test on a much slower machine. – rwbyrd Aug 03 '15 at 20:02

2 Answers2

2

It seems to me you are using a for loop where you want a while loop as the for loop is going in the range of 0:5, but you are trying to alter it internally (cnt = cnt + 1) for example. With a while loop you can set it initially (cnt = 0) and then while cnt < 5 go through the body. I think this will resolve your issue. Sorry for the poor wording.

replace

for cnt in range (0, 5):

with

cnt = o
while cnt < 5:
    {body}
Going hamateur
  • 421
  • 3
  • 4
  • That's exactly what I did once I saw your suggestion @Going hamateur. Thanks for your answer. It resolved my issue. I'm curious, is there a way to achieve the same goal using a 'for' loop? – rwbyrd Aug 03 '15 at 20:09
2

I'm making sure the table has been at least partially loaded before I continue with my testing. I need at least 3 objects to be listed in the table to confirm a test I'm doing. This helps me when running the same test on a much slower machine.

You don't have to do it manually. Selenium has the Explicit Wait functionality built-in. Basically, you provide a callable which it would execute every 500ms (by default) until the callable evaluates to True but up to the M seconds you configure.

In your case, you need a custom Expected Condition to wait for more than N elements to become present:

from selenium.webdriver.support import expected_conditions as EC

class wait_for_n_elements(object):
    def __init__(self, locator, count_):
        self.locator = locator
        self.count = count_

    def __call__(self, driver):
        try:
            elements = EC._find_elements(driver, self.locator)
            return len(elements) >= self.count
        except StaleElementReferenceException:
            return False

Usage:

from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait    

wait = WebDriverWait(driver, 10)
wait.until(wait_for_n_elements((By.XPATH, "//select[@id='active_config']/option"), 3))

Here, we are telling selenium to wait until 3 or more options would become present checking the condition every 500ms, but up to 10 seconds. If in 10 seconds the condition would not be satisfied, you'll get a TimeoutException.

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • This is great, @alecxe. How would I change this if I also wanted to create the same function to wait until the whole table is loaded, if that's possible? Would you need to know the number of elements you're expecting? – rwbyrd Aug 03 '15 at 20:15
  • @rwbyrd thanks, this is webpage-specific, do you know the number of options beforehand? – alecxe Aug 03 '15 at 20:23
  • No, @alecxe the number of options can vary anywhere from 2-100. – rwbyrd Aug 03 '15 at 20:33
  • @rwbyrd okay, but, how you personally, as a user, determine that the table is loaded? – alecxe Aug 03 '15 at 20:34
  • To get around knowing if the whole table has been loaded, I've been doing a search for a specific profile I'm looking for using a method I created. assertExpectedRegexConditionTrue(self.driver, "By.ID", "active_config", r"^[\s\S]*" + option + "[\s\S]*$", "60") Where it waits 60 seconds to see if the expected option is loaded & then fails with a code stating the expected option wasn't available. – rwbyrd Aug 03 '15 at 20:36
  • @rwbyrd what if you make, say, an XPath locator to find a specific text inside an option and would use a built-in `EC.presence_of_element_located` as a wait condition?.. – alecxe Aug 03 '15 at 20:38
  • That's pretty similar to what my method can do @alecxe but using your method I think would make it more clean & easier to understand. – rwbyrd Aug 03 '15 at 20:40