1

I've been using the PyQt5 for a while, and want tests to be performed on the GUI, with Windows 10. The Appium seems to be a good option for the purpose. For now, I can access the widget by setting the accessbleName in the Qt Designer. However, how can I access the widget's text showing on the window? Haven't found anything on the official docs yet. Thanks.

For example, there's a login window. Each time when the user enters the wrong combination of username and password, there would be a message showing Invalid username or password.

Here is my current PyQt5 code:

class LoginScreen(QDialog):
  ''' The page where the client can login '''
  def __init__(self):
    super(LoginScreen, self).__init__()
    loadUi('login.ui', self)
    # before coding, change the objectName in the qt designer
    self.passwordField.setEchoMode(QtWidgets.QLineEdit.Password)
    self.login.clicked.connect(self.login_function)
  
  def login_function(self):
    user = self.emailField.text() # might be tested with appium webdriver
    password = self.passwordField.text()

    if len(user) == 0 or len(password) == 0:
      self.errorMsg.setText("Please input all fields.") # how could I get the text?
    else:
      conn = sqlite3.connect(shop_data)
      cur = conn.cursor() # execute the query
      query = f"SELECT password FROM login_info WHERE username = '{user}' "
      cur.execute(query)
      result_pass = cur.fetchone()[0] # return tuple; 
      print(result_pass) # the password printed in the console
      if result_pass == password:
        print("Successfully logged in")
        self.errorMsg.setText("") # how could I get the text?
      else:
        self.errorMsg.setText("Invalid username or password") # how could I get the text?

Here is the Appium testing code, only focusing on the test case:

def testLoginFailure(self):
  self.driver.implicitly_wait(10)
  self.driver.find_element_by_name("login").click()
  self.driver.find_element_by_name("username").send_keys("marysmith")
  self.driver.find_element_by_name("password").send_keys("123456")
  self.driver.find_element_by_name("loginPageLogin").click()
  # the text would be "errorMsg"; "errorMsg" != "Invalid username or password"
  self.assertEqual(self.driver.find_element_by_name("errorMsg").text, "Invalid username or password") 
Woden
  • 1,054
  • 2
  • 13
  • 26
  • Qt properties are accessible as function calls, shouldn't it be `self.driver.find_element_by_name("errorMsg").text()`? – musicamante Aug 19 '21 at 10:27
  • I've tried this, it gives me `TypeError: 'str' object is not callable`. – Woden Aug 19 '21 at 10:29
  • For now, I could only use `.is_displayed()` to make sure the text is shown, but cannot ensure the exact text. – Woden Aug 19 '21 at 10:42
  • Oooh, sorry, I get it now: `find_element_by_name` doesn't return the *Qt widget*. Unfortunately I don't know how Appium works, but in any case, have you tried to print that text and set the default label text to something else, just to be sure that, at least, the property is correctly read and the problem might be elsewhere. Also, I see mentions about `getText()`, have you tried it? – musicamante Aug 19 '21 at 10:47
  • `getText()` is not the Python syntax, but I've got an idea. I'll let you know if it succeeds. – Woden Aug 19 '21 at 10:50
  • I GOT it!! Since the default behavior of the widget's name is according to the text above it. I took out the `accessbleName` and make it empty. Then, assert that the correct text is displayed. The syntax would be `self.assertEqual(self.driver.find_element_by_name("Invalid username or password").is_displayed(), True)`. Thank you, my friend. – Woden Aug 19 '21 at 10:54
  • 1
    If you found a suitable solution, then use the related field to provide your own answer to your question. – musicamante Aug 19 '21 at 11:10

1 Answers1

0

The accessbleName in the Qt designer allows the Appium inspector to find the widget, such as a button. Without the accessbleName, the inspector the default behavior would be searching the text attached on the top of the widget as the name. Therefore, the answer is to find the text directly, not treating the name as a variable.

Therefore, I can assert the text displayed on the screen.

self.assertEqual(self.driver.find_element_by_name("Invalid username or password").is_displayed(), True)
Woden
  • 1,054
  • 2
  • 13
  • 26