1

I'm working a project to automate logging into a couple of sites and creating users in those sites. It seems to me Selenium is skipping lines and not waiting for user input in the console. I have notated the areas where it skips with python comment marks. I have also replaced specific information with generalized information. Is there something I need to do to force Selenium to wait on console input or is it a bug? Any advice would be appreciated. Also, I'm relatively new to Python as a whole and any bad practices you see please let me know. Below is my code so far.

Note: Little backstory. I started on website2 first and ran into a few issues I'm still working through so I moved to website1 and the code is incomplete as I'm building code as I progress through the layers of the site.

def website1Login():
    driver.get('website1.com')
    username = input("Please enter your username: ")  # Waits for action
    searchBox = driver.find_element_by_name('username')
    searchBox.send_keys(username)
    password = input("Please enter your password: ")  # skips action
    searchBox = driver.find_element_by_name('password')
    searchBox.send_keys(password)
    searchBox.submit()


def website1Create():
    webOrExchange = 0
    webOrExchange = input("Select a service: \n" # Skips action
                          "1. Webmail\n"
                          "2. Exchange\n\n"
                          "Service Selected: ")
    time.sleep(10)
    if webOrExchange == 1:
        webmailSelect = driver.find_element_by_partial_link_text('EmailHosting/Mail/Mailboxes/List.aspx')
        webmailSelect.click()
        time.sleep(2)
    else:
        exchangeSelect = driver.find_element_by_partial_link_text('Exchange/Mail/Mailboxes/List.aspx')
        exchangeSelect.click()
        time.sleep(2)


def website2login():
    driver.get('website2.com')
    username = input("Please enter your username: ") # Waits for this action
    searchBox = driver.find_element_by_id('USER')
    searchBox.send_keys(username)
    password = input("Please enter your password: ") # Skips this action
    searchBox = driver.find_element_by_id('PASSWORD')
    searchBox.send_keys(password)
    searchBox.submit()


def website2Create():
    idmSelect = driver.find_element_by_id('Identity Management')  # Selects Identity Management app
    idmSelect.click()
    time.sleep(15)
    createNewUser_Select = WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="request_category2"]/ul/li'))  # Selects Create New User
    )
    createNewUser_Select.click()
    time.sleep(10)
    driver.quit()


def main():
    website1Login()
    website1Create()
    # website2login()
    # website2Create()


main()
DebanjanB
  • 118,661
  • 30
  • 168
  • 217
Austin
  • 21
  • 4

1 Answers1

0

To start with, there seems to be some mixup between the attribute value within the Locator Strategy and variable name being used.

You have used:

searchBox = driver.find_element_by_name('username')

But again, username is a string variable holding the actual username from the console.

As per best practices, the variable names should be unique as per their scope.

This step may solve your current issue.


flush the input stream

You can also flush the input stream as follows:

  • On Windows systems you can use msvcrt.getch() method from the msvcrt module.

    • msvcrt.getch(): Read a keypress and return the resulting character. Nothing is echoed to the console. This call will block if a keypress is not already available, but will not wait for Enter to be pressed. If the pressed key was a special function key, this will return '\000' or '\xe0'; the next call will return the keycode. The Control-C keypress cannot be read with this function.
    • Example:

      import msvcrt
      import sys
      
      x = input("First Input: ")
      print("First Input: {}".format(x))
      sys.stdout.flush()
      # Try to flush the buffer
      while msvcrt.kbhit():
          msvcrt.getch()
      y = input("Second Input: ")
      print("Second Input: {}".format(y))
      
    • Console Output:

      First Input: asdfg
      First Input: asdfg
      Second Input: ;lkjh
      Second Input: ;lkjh
      
  • On Unix systems you can use termios.tcflush(fd, queue) method from the termios

    • termios.tcflush(fd, queue): Discard queued data on file descriptor fd. The queue selector specifies which queue: TCIFLUSH for the input queue, TCOFLUSH for the output queue, or TCIOFLUSH for both queues.
    • Example:

      from termios import tcflush, TCIFLUSH
      import time,sys
      
      a = raw_input("First input ")
      b = raw_input("Second input ")
      time.sleep(5)
      tcflush(sys.stdin, TCIFLUSH)
      a = raw_input("Third input ")
      b = raw_input("Fourth input ")
      
    • Console Output:

      First Input 1
      Second Input 2
      33
      33
      Third Input 3
      Fourth Input 4
      
DebanjanB
  • 118,661
  • 30
  • 168
  • 217
  • `"username"` is a *string* while `username` is a variable that might contain *any data of any type*. Where is *mixup* in this case and about which *best practices* are you talking about? Also how can *input stream flushing* solve this issue? – Andersson Oct 31 '18 at 12:20
  • 1
    @DebanjanB your example code solved my issue thank you. I'm not sure I fully understand it but I will definitely read up on it. I need to go back and clean up my variables. I was pretty sloppy in naming them in the beginning. – Austin Oct 31 '18 at 14:36