Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Помогите разобраться с тестом


(Шевченко Владислав) #1

Дано: функционал перевода сотрудника в работники  - несколько вкладок с кучей инфы. Поля ввода (input), чекбоксы, дропдауны, дэйтпикеры. Всего полей ~ 80.

Заполняю это все разными мапами.

Проверку просто перевода сотрудника уже написал.

Нужно: проверить что данные которые я забил и сохранил из БД попадают на UI.

 

Проблемы: 

1) Поля ввода разных данных. Думал сначала сделаю одну карту для заполнения которая будет типа ожидаемым результатом, а вторую буду собирать из актуальных результатов. Но так как поля разные приходится заполнять разными картами и методами которые нажимают чекбоксы. Таким образо сравнивать в конце придется несколько карт. 

Если у кого нибудь было нечто похожее  - поделитесь опытом, а то я уже порядком запутался. Сечас думаю писать один большой тест по всем проверкам какрт сразу или отдельные тесты на каждую карту результатов.

 

 

 

 


(nigilit) #2

Если под картой вы имеете ввиду HashMap то внесите в нее помимо имени поля и значения, еще его тип.

Вот пример даных на json:

{
   "_date":{
      "options":{
         "existingValue":"04/25/2013",
         "type":"date",
         "editValue":"05/25/2013",
         "defaultValue":"03/26/2013"
      },
      "validation":{
         "isRequired":"true",
         "isDate":"true"
      }
   },
   "title":{
      "options":{
         "existingValue":"First Title For Selenium Tests",
         "type":"text",
         "editValue":"Edit Title For Selenium Tests",
         "defaultValue":"Default Title For Selenium Tests"
      },
      "validation":{
         "isRequired":"true"
      }
   },

   "enabled":{
      "options":{
         "existingValue":"true",
         "type":"checkbox",
         "editValue":"false",
         "defaultValue":"true"
      },
      "validation":{
      }
   }

}

 

Дальше данные можете вносить те которые надо и от которых надо отталкиваться в зависимости от теста


(asolntsev) #3

Зачем делать сложные выкрутасы с Map?

Почему просто не сделать естественным путём: заполнить все нужные поля, кликнуть "Сохранить" и проверить, что во всех полях нужные значения?

То есть как-то так:

 

$("#first_name").val("John");

$("#last_name").val("Connor");

$... ещё 40 полей...

 

$("#save").click();

 

 

$("#first_name").shouldHave(value("John"));

$("#last_name").shouldHave(value("Connor"));

$... ещё 40 полей...

 
В этом варианте, конечно, будут продублированы все эти тестовые значения, но в тесте это не страшно. И это всё равно проще и надёжнее, чем строить какую-то сложную логику для заполнения формы по "карте". 

(Шевченко Владислав) #4

asolntsev т.е. на каждый assert будет один тест - итого куча тестов вместо нескольких. Не я все таки считаю что нужно по максимуму использовать все возможности языка


(CyonidE) #5

в этом случае логичнее было бы использовать Excel например для сохранения тестовых данных в таблице и оттуда их тянуть - одним дата провайдером... также там же можно и хранить правильные и неправильные варианты данных и просто реализовать их сравнение, чтобы не использовать множество maps... 


(Шевченко Владислав) #6

хотелось бы посмотреть на реализацию такого подхода на java. 


(asolntsev) #7

Почему много тестов? Нет, можно сделать один тест, в котором проверять 40 полей.


(Шевченко Владислав) #8

с предидущим вопросом я решил все таки собирать значения в Map.

 

теперь появилось еще одно странно поведение.

есть метод

 public Map getAllData(Collection<String> namesOfElements) {
        Map<String, String> getData = new HashMap<String, String>();
 
        for (String element : namesOfElements) {
            WebElement webElement = getWebElementByName(element);
 
            if (webElement.getAttribute("role").equals("listbox")) {
                String listboxTextValue = webElement.findElement(By.cssSelector("span span span")).getText();
                getData.put(element, listboxTextValue);
            } else if (webElement.getAttribute("type").equals("text")) {
                String value = webElement.getAttribute("value");
                getData.put(element, value);
            } else {
                String text = webElement.getText();
                getData.put(element, text);
            }
        }
 
        return getData;

    } 

который призван собирать текстовые значения всех текстовых полей, input полей и выпадающих списков.

 

Проблема заключается в том что на одном из элементов: 

 

private WebElement permitAddressEstateOfficeApartmentDrdwn;
@FindBy(xpath = "//div[@data-bind = 'with: permitAddress']//input[@data-bind = 'value:SelectedEstateBuildingValue, disable:isReadOnly']")
 
на этапе 
 else if (webElement.getAttribute("type").equals("text")) 
 
HTML код этого элемента 
<div class="controls">
<input class="input-medium" type="text" data-bind="value:SelectedEstateBuildingValue, disable:isReadOnly"/>
</div>
 
тест валится, я начал дебажить и увидел, что на этом элементе программа уходит куда-то в public class MethodInvocationHelper и в цикл уже не возвращается.
 
PS в дебаге я просматривал webElement.getAttribute("value") и он возвращал стрингу с нужным мне значением. Почему он не мапит это значение - мне непонятно.
 
 
Помогите кто чем может.
 

 

 


(nigilit) #9

Дайте полное описание ошибки из консоли. Какой Ексепшн возвращает?

Кроме того возможно проблема в PageFactory - возможно елемент еще не доступен в момент инициализации страницы. Попробуйте передать driver и найти елемент через

driver.findElement(By.xpath("//div[@data-bind = 'with: permitAddress']//input[@data-bind = 'value:SelectedEstateBuildingValue, disable:isReadOnly']"));

 

Класс на который вы ссилаетесь относиться к TestNG https://github.com/cbeust/testng/blob/master/src/main/java/org/testng/internal/MethodInvocationHelper.java

Там проблем быть не должно.

На какую последнюю строку кода написаного вами выдает ошыбку?

 

Сложно о чем то говорить без полного trace сообщения из консоли.


(nigilit) #10

И да кстати:

WebElement webElement = getWebElementByName(element);

У вашего елемента нету аттрибута 'name':

<div class="controls">
   <input class="input-medium" type="text" data-bind="value:SelectedEstateBuildingValue, disable:isReadOnly"/>
</div>

(Шевченко Владислав) #11

это просто название метода, передается туда совсем не name

 

 

protected WebElement getWebElementByName(String fieldName) {
        try {
            Field field = this.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            WebElement we = (WebElement) field.get(this);
            field.setAccessible(false);
            return we;
        } catch (NoSuchFieldException e) {
            e.printStackTrace(); 
        } catch (IllegalAccessException e) {
            e.printStackTrace(); 
        }
        throw new IllegalArgumentException("The field with name " + fieldName + " hasn't been found");
    }

(Шевченко Владислав) #12

во время дебага сделал webdriver.findElement(By.xpath("//div[@data-bind = 'with: permitAddress']//input[@data-bind = 'value:SelectedEstateBuildingValue, disable:isReadOnly']")).isEnabled()   = true 

Ошибка при провале теста 

 

java.lang.NullPointerException
at com.luxoft.inthr2.pages.BasePage.getAllData(BasePage.java:73)
at com.luxoft.inthr2.test.TransferToEmployeeDataSaveTest.verifySaveData(TransferToEmployeeDataSaveTest.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:182)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:158)
 
и вот два скриншота перед и после провала
 
 
 
 
 
 

(nigilit) #13

Все предельно просто:

Когда вы делаете:

if (webElement.getAttribute("role").equals("listbox"))

 

webElement.getAttribute("role") - возврщает null. Такого атрибута у елемента нету.

null.equals("listbox")) - выдает ошыбку

Для того чтоб заработало нужно сделать:

if (webElement.getAttribute("role")!=null&&webElement.getAttribute("role").equals("listbox"))

При этом делать проверку

webElement.getAttribute(%attribute%)!=null при любых операциях с аттрибутами в вашем случае


(asolntsev) #14

Ну вот не слышаете вы умного дядьку!

Говорю вам, не нужны вам все эти заморочки с мапами, рефлекшинами и т.д. Это всё аццки услжняет тесты и не даёт никаких преиуществ.

Напишите прямо в лоб - это будет работать надёжно:

 

$("#first_name").val("John");

$("#last_name").val("Connor");

$("#save").click();

$("#first_name").shouldHave(value("John"));

$("#last_name").shouldHave(value("Connor"));


(nigilit) #15

Поправил комментарий: .isEmpty() для null тоже вызывать нельзя


(Шевченко Владислав) #16

извините я не очень понимаю скрипт (это же джаваскрипт? ;-))

если я правильно поянл вашу мысль то:

поля заполнить я могу через методы. типа

setValue(String value) {

webElement.sendKeys(value)

таким образом для каждого поля pagefactory у меня должен быть сеттер и геттер на моей page.

что касается $("#first_name").shouldHave(value("John"))

то тут я могу делать assertEquals(String, String) и так для каждой пары.

таким образом кол-во assert'ов  = кол-ву елементов. это если не пользовать коллекции.

такая у меня логика - может я чего-то не понимаю в меру своей неопытности. 

 

 

 

 


(Шевченко Владислав) #17

спасибо вам большое. действительно все просто, но для меня не очевидно было


(asolntsev) #18

Нет, это не JavaScript, это код на Java с использованием библиотеки Selenide (синтаксис похож на JavaScript, да).

Никаких sendKeys и assertEquals делать не нужно, никаких геттеров/сеттеров не нужно. Просто пишете код как я написал - и заработает. 


(Шевченко Владислав) #19

ага понятно, спасибо, я обязательно попробую, выглядит это очень интересно