Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Не вводятся русские значения с помощью send_keys() (python)


(Елена Перфильева) #1

Запускаю демонстрационные тесты appium-а на python (https://github.com/appium/sample-code/tree/master/sample-code/examples), а именно:

import os
import unittest
from appium import webdriver
from time import sleep

# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
)

class ContactsAndroidTests(unittest.TestCase):
    def setUp(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '4.2'
        desired_caps['deviceName'] = 'Android Emulator'
        desired_caps['app'] = PATH(
            '../../../sample-code/apps/ContactManager/ContactManager.apk'
        )
        desired_caps['appPackage'] = 'com.example.android.contactmanager'
        desired_caps['appActivity'] = '.ContactManager'

        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def tearDown(self):
        self.driver.quit()

    def test_add_contacts(self):
        el = self.driver.find_element_by_accessibility_id("Add Contact")
        el.click()

        textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
        textfields[0].send_keys("Appium User")
        textfields[2].send_keys("someone@appium.io")

        self.assertEqual('Appium User', textfields[0].text)
        self.assertEqual('someone@appium.io', textfields[2].text)

        self.driver.find_element_by_accessibility_id("Save").click()

        # for some reason "save" breaks things
        alert = self.driver.switch_to_alert()

        # no way to handle alerts in Android
        self.driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)').click()

        self.driver.press_keycode(3)



if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
    unittest.TextTestRunner(verbosity=2).run(suite)

textfields[0].send_keys(“Appium User”) отправляет в соответствующее поле текст.

Меняю текст на русский (не забыв перевести его в юникод и добавить в начале файла # coding: utf-8), т.е. запускаю следующий код

# coding: utf-8
import os
import unittest
from appium import webdriver
from time import sleep

# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
)

class ContactsAndroidTests(unittest.TestCase):
    def setUp(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '4.2'
        desired_caps['deviceName'] = 'Android Emulator'
        desired_caps['app'] = PATH(
            '../../../sample-code/apps/ContactManager/ContactManager.apk'
        )
        desired_caps['appPackage'] = 'com.example.android.contactmanager'
        desired_caps['appActivity'] = '.ContactManager'

        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def tearDown(self):
        self.driver.quit()

    def test_add_contacts(self):
        el = self.driver.find_element_by_accessibility_id("Add Contact")
        el.click()

        textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
        textfields[0].send_keys(u"Алиса")
        textfields[2].send_keys("someone@appium.io")

        self.assertEqual('Appium User', textfields[0].text)
        self.assertEqual('someone@appium.io', textfields[2].text)

        self.driver.find_element_by_accessibility_id("Save").click()

        # for some reason "save" breaks things
        alert = self.driver.switch_to_alert()

        # no way to handle alerts in Android
        self.driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)').click()

        self.driver.press_keycode(3)



if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
    unittest.TextTestRunner(verbosity=2).run(suite)

Текстовое поле остаётся пустым, при этом какой-либо ошибки по этому поводу не выдаётся.
Подскажите, что я делаю не так?


(rmerkushin) #2

Пробовали убрать u перед Алисой? Может ему тип не нравится? u’Алиса’ - unicode, ‘Алиса’ - string


(Елена Перфильева) #3

Пробовала, тогда всё взрывается вот с такой ошибкой на этой строчке:
UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xd0 in position 0: unexpected end of data


(rmerkushin) #4

Попробуйте поиграться с encode\decode utf-8, возможно поможет. В python частенько бывают затыки с кодировками ) А так, нужно смотреть внутря appium чего он там воротит.


(Елена Перфильева) #5

Взрывается((
Коллеги из соседней команды пишут тесты для ios, говорят, что им достаточно u перед русской строкой написать и send_keys прекрасно работает, никакой дополнительной магии.
Неужели никто не сталкивался с такой проблемой?


(Максим Малунов) #6

Может поможет
Ввод русских значений в input

В python 2.7 все символы по дефолту оперируются как ASCII, а не юникод. Соответственно в ASCII нет русских символов и для этого надо использовать юникод. Что это означает:

Файл с исходным кодом должен быть сохранен как utf-8
В начале файла должна быть нотация кодировки, которая используется # -- coding: utf-8 --
Все строковые переменные, которые выходят за таблицу ASCII должны быть представлены в как unicode с префиксом u’некоторый текст’ (с)


(Елена Перфильева) #7

Решилось добавлением
desired_capabilities[‘unicodeKeyboard’] = ‘True’.


(Zolotarevkirill) #8

Если работать через параметр desired_capabilites[‘unicodeKeyboard’] то подключается аппиумская клава, которая не переключается обратно. И самое прикольное что ее не видно. И вызвать или открыть ее как то что бы работать с ней по координатам не возможно. В моем случае это было критично из-за не простого дизайна приложения. Мне нужна была кнопка энтер на клавиатуре для ввода поисква и еще в ряде случаев. Так как апиумовская клава пропадала мне нужно было решение с сохранением стандартной клваиатуры. Написал функцию набора слов на русской раскладке. Может пригодится. Есть еще что доработать но все же.

def send_keys_rus(self, text):
“”"
Gets the text. Splits it into words by spaces.
Next, press the keyboard on the coordinates of the letters received in each word.
:param text:
:return:
“”"
arr_string = text.split(" ")
count_string = len(arr_string)
count = 0
height = self.driver.get_window_size()[‘height’]
width = self.driver.get_window_size()[‘width’]
action = TouchAction(self.driver)
logger.info('Вводим по координатам слово ’ + str(text))

    while count < count_string:

        for char in arr_string[count]:
            coord_string = self.get_coord_string(char)
            coord_split = coord_string.split(" ")
            w = width * float(coord_split[0])
            h = height * float(coord_split[1])
            action.tap(None, w, h, 1).perform()

        count += 1
        action.tap(None, width * 0.60, height * 0.95, 1).perform()

def get_coord_string(self, char):
    """
    Receives the input of the Russian letter. Puts it in lowercase. Next, use it as a key to the hash table.
    Returns a string with coordinates.
    :param char:
    :return string coordinates:
    """

    lower_char = char.lower()

    coord = dict()
    coord['а'] = '0.30 0.80'
    coord['б'] = '0.80 0.90'
    coord['в'] = '0.20 0.80'
    coord['г'] = '0.55 0.70'
    coord['д'] = '0.80 0.80'
    coord['е'] = '0.40 0.70'
    coord['ё'] = '0.40 0.70'
    coord['ж'] = '0.90 0.80'
    coord['з'] = '0.90 0.70'
    coord['и'] = '0.50 0.90'
    coord['й'] = '0.50 0.90'
    coord['к'] = '0.30 0.70'
    coord['л'] = '0.70 0.80'
    coord['м'] = '0.40 0.90'
    coord['н'] = '0.50 0.70'
    coord['о'] = '0.60 0.80'
    coord['п'] = '0.40 0.80'
    coord['р'] = '0.50 0.80'
    coord['с'] = '0.30 0.90'
    coord['т'] = '0.60 0.90'
    coord['у'] = '0.20 0.70'
    coord['ф'] = '0.01 0.80'
    coord['х'] = '0.99 0.70'
    coord['ц'] = '0.10 0.70'
    coord['ч'] = '0.20 0.90'
    coord['ш'] = '0.70 0.70'
    coord['щ'] = '0.70 0.70'
    coord['ъ'] = '0.70 0.90'
    coord['ы'] = '0.10 0.80'
    coord['ь'] = '0.70 0.90'
    coord['э'] = '0.99 0.80'
    coord['ю'] = '0.90 0.90'
    coord['я'] = '0.15 0.90'

    return coord[lower_char]

(vmaximv) #9

Thanks. You made my Friday.