Selenium RC (Java): Основные операции в действии. Часть 2


(Mykhailo Poliarush) #1

Часть 1, Часть 3

Работа с полем загрузки файлов

Одним из каверзных стандартных элементов управления на веб-страницах с точки зрения работы Selenium-a является поле загрузки файла. Фактически это текстовое поле и кнопка. В чем сложность? Сложность в том, что нажатие на кнопку Selenium-ом напрямую не делается (да и не нужно, если так посмотреть), а текстовое поле в общем случае доступно только для чтения, так что просто так ввести туда путь к файлу не получится. Это связано с тем, что Selenium-сервер взаимодействует с тестируемым веб-приложением путем посылки JavaScript-команд, а у объектов, соответствующих полям ввода файлов, атрибут value закрыт для записи. Это стандартное ограничение браузеров, блокирующее возможность автоматической загрузки произвольных файлов. Не стоит забывать, что клиентские скрипты несут в себе много чего вредоносного. Отчасти поэтому те же файлы с расширением js многими почтовиками блокируются. Это просто система защиты.

Тем не менее, данные проблемы так или иначе можно обойти. Итак, рассмотрим следующую секцию нашей тестовой страницы:






Реализуем шаг, в котором нам надо ввести некоторый текст в поле ввода файла и проверить, что текст введен корректно. Есть 2 способа ввести текст:

  • platform-specific - заключается в использовании сторонних библиотек, которые имитируют ввод с клавиатуры. В частности для Java можно воспользоваться классом java.awt.Robot.
  • browser-specific - заключается в том, что для определенных браузеров в определенном режиме поле ввода файлов доступно для записи на программном уровне. В частности, в режиме *chrome Selenium в состоянии ввести текст в поле ввода файла обычным вызовом type.

Из этих 2-х способов предпочтительнее выглядит 2-й по ряду причин. Во-первых, нет привязки к языку программирования, соответственно, данный подход универсален в контексте используемого языка программирования. Во-вторых, зачастую, использование внешних средств, имитирующих пользовательский ввод, привязывает код к конкретной группе операционных систем. И наконец, в-третьих, в большинстве случаев имитация ввода сводится к посылке некоторых сигналов "в эфир". Соответственно, если нужное нам окно не активно, то текст введется неизвестно куда. А ведь одно из удобств Selenium-a заключается в том, что тесты могут выполняться в фоновом режиме, в то время как пользователь может на той же машине заниматься своими делами.

Итак, нам нужно перейти в *chrome-режим, открыть страницу и ввести текст. Как-то так:

{syntaxhighlighter brush: java;fontsize: 100; first-line: 1; highlight: [[86,87,88,89,90,91,92,93,94,95,96,97]]; }package com.example.tests;
import com.thoughtworks.selenium.*;

import java.util.regex.Pattern;

public class NewTest extends SeleneseTestCase {

  public void setUp() throws Exception {
    setUp("c:\\index.htm", "*firefox");
  }

  public void testNew() throws Exception {
       selenium.open("c:\\index.htm");
       selenium.type("text_field" , "Sample Text" );
       assertEquals( selenium.getValue( "text_field" ) , "Sample Text" );
       selenium.type("text_area" , "Sample Text" );
       assertEquals( selenium.getValue( "text_area" ) , "Sample Text" );

       selenium.click( "radio_2" ); // Select item via click
       assertTrue( selenium.isChecked( "radio_2" ) );
       selenium.check( "radio_1" ); // Select item via check
       assertTrue( selenium.isChecked( "radio_1" ) );

       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );
       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );

       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "false" ) );

       if( selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "true" ) );


       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       selenium.click( "deactivated_btn" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "deactivated_btn" )
       );

       selenium.click( "btn_1" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "btn_1" )
       );

       selenium.click( "btn_2" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getText( "btn_2" )
       );

       selenium.select( "single_list" , "Option 2" );
       assertEquals( 
            selenium.getSelectedLabel( "single_list" ),
            "Option 2"
       );

       selenium.select( "multi_list" , "Multi Option 2" );
       selenium.addSelection( "multi_list" , "Multi Option 3" );
       String[] selectedOpts = selenium.getSelectedLabels( "multi_list" );
       assertEquals( 
            selectedOpts[0], 
            "Multi Option 2"
       );
       assertEquals( 
            selectedOpts[1],
            "Multi Option 3"
       );

       selenium.stop();
       setUp("c:\\index.htm", "*chrome");
       selenium.open("c:\\index.htm");
       selenium.type( "file_field" , "Some Text" );
       assertEquals(
            selenium.getValue( "file_field" ),
            "Some Text"
       );
       selenium.stop();
       setUp("c:\\index.htm", "*firefox");
       selenium.open("c:\\index.htm");
 }

}{/syntaxhighlighter}

Рассмотрим выделенный фрагмент детальнее. Мы остановили текущую сессию Selenium-a, вызвав метод stop. После этого, мы создали новую сессию, но на этот раз мы запустили FireFox в небезопасном режиме, открыли страницу и уже работаем с полем ввода файла, как с обычным текстовым полем. После наших действий, мы выходим из установленного режима и восстанавливаем сессию основного используемого браузера.

На практике, поле ввода файла не идет в одиночку. Соответственно, подобные операции, требующие переключения на определенный браузер, группируются в отдельные методы, которые выполняют действия в *chrome-режиме в том объеме, в котором необходимо. Итак, основной идеей работы с полем ввода файла является то, что в *chrome-режиме с ним можно работать как с текстовым полем.

Работа со стандартными окнами сообщений браузеров

Последняя рассматриваемая секция содержит в себе кнопки, клик на которые выведет определенные сообщения. У браузера есть 3 типа окон сообщений:

  • alert - обычное окно сообщения, у которого есть только одна кнопка, которая собственно это окно и закрывает
  • confirmation - окно подтверждения некоторого действия, характеризующееся наличием 2-х кнопок: "ОК" и "Отмена" с соответствующим набором действий при нажатии на ту или иную кнопку
  • prompt - представляет собой диалог, в который надо ввести текст.

Итак, вот наша секция:





Реализуем следующий сценарий:

  • Кликнуть на кнопку "Call Alert" и проверить, что появилось сообщение "This is Alert"
  • Закрыть окно
  • Кликнуть на кнопку "Call Confirmation" и проверить, что появилось сообщение "This is confirmation".
  • Закрыть окно, нажав ОК.
  • Кликнуть на кнопку "Call Prompt", ввести текст в появившемся окне и нажать ОК.

Сразу следует отметить, что Selenium устроен так, что он перехватывает появление стандартных окон сообщений браузера, так что визуально во время выполнения теста они отображаться не должны. Если были выполнены какие-то операции, после которых должно появиться какое-то сообщение, то сам факт появления сообщения надо как-то перехватить, иначе любое последующее действие вызовет ошибку вида: "There was unexpected alert". В зависимости от типа окна сообщения эту задачу выполняют следующие методы:

  • isAlertPresent
  • isConfirmationPresent
  • isPromptPresent

Они возвращают true, если диалог соответствующего типа появился. Но обнаружить окно мало. Надо еще считать сообщение и закрыть диалог. В частности это нужно для шагов 1-4. В Selenium-e эти действия совмещены. В частности есть 2 метода:

  • getAlert
  • getConfirmation

которые возвращают текст сообщения и закрывают окно. Этих знаний уже достаточно для реализации первых 2-х шагов сценария. Реализация имеет вид:

{syntaxhighlighter brush: java;fontsize: 100; first-line: 1; highlight: [98,99,100]; }package com.example.tests;
import com.thoughtworks.selenium.*;

import java.util.regex.Pattern;

public class NewTest extends SeleneseTestCase {

  public void setUp() throws Exception {
    setUp("c:\\index.htm", "*firefox");
  }

  public void testNew() throws Exception {
       selenium.open("c:\\index.htm");
       selenium.type("text_field" , "Sample Text" );
       assertEquals( selenium.getValue( "text_field" ) , "Sample Text" );
       selenium.type("text_area" , "Sample Text" );
       assertEquals( selenium.getValue( "text_area" ) , "Sample Text" );

       selenium.click( "radio_2" ); // Select item via click
       assertTrue( selenium.isChecked( "radio_2" ) );
       selenium.check( "radio_1" ); // Select item via check
       assertTrue( selenium.isChecked( "radio_1" ) );

       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );
       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );

       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "false" ) );

       if( selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "true" ) );


       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       selenium.click( "deactivated_btn" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "deactivated_btn" )
       );

       selenium.click( "btn_1" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "btn_1" )
       );

       selenium.click( "btn_2" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getText( "btn_2" )
       );

       selenium.select( "single_list" , "Option 2" );
       assertEquals( 
            selenium.getSelectedLabel( "single_list" ),
            "Option 2"
       );

       selenium.select( "multi_list" , "Multi Option 2" );
       selenium.addSelection( "multi_list" , "Multi Option 3" );
       String[] selectedOpts = selenium.getSelectedLabels( "multi_list" );
       assertEquals( 
            selectedOpts[0], 
            "Multi Option 2"
       );
       assertEquals( 
            selectedOpts[1],
            "Multi Option 3"
       );

       selenium.stop();
       setUp("c:\\index.htm", "*chrome");
       selenium.open("c:\\index.htm");
       selenium.type( "file_field" , "Some Text" );
       assertEquals(
            selenium.getValue( "file_field" ),
            "Some Text"
       );
       selenium.stop();
       setUp("c:\\index.htm", "*firefox");
       selenium.open("c:\\index.htm");

       selenium.click( "alert_btn" );
       assertTrue( selenium.isAlertPresent() );
       assertEquals( selenium.getAlert(), "This is Alert" );
 }

}{/syntaxhighlighter}

C confirmation-сообщениями добавляется небольшая деталь: нужно указать, какую кнопку нажать для закрытия диалога данного типа. В дополнение к вышеиспользованным методам, для confirmation-диалогов есть возможность выбора кнопки, которую надо нажать. Для этого используются методы:

  • chooseOkOnNextConfirmation
  • chooseCancelOnNextConfirmation

которые вызываются до того, как будет вызван метод getConfirmation. То есть, мы как бы заказываем заранее необходимое действие. Учитывая вышесказанное, реализуем шаги 3 и 4:

{syntaxhighlighter brush: java;fontsize: 100; first-line: 1; highlight: [102,103,104,105]; }package com.example.tests;
import com.thoughtworks.selenium.*;

import java.util.regex.Pattern;

public class NewTest extends SeleneseTestCase {

  public void setUp() throws Exception {
    setUp("c:\\index.htm", "*firefox");
  }

  public void testNew() throws Exception {
       selenium.open("c:\\index.htm");
       selenium.type("text_field" , "Sample Text" );
       assertEquals( selenium.getValue( "text_field" ) , "Sample Text" );
       selenium.type("text_area" , "Sample Text" );
       assertEquals( selenium.getValue( "text_area" ) , "Sample Text" );

       selenium.click( "radio_2" ); // Select item via click
       assertTrue( selenium.isChecked( "radio_2" ) );
       selenium.check( "radio_1" ); // Select item via check
       assertTrue( selenium.isChecked( "radio_1" ) );

       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );
       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );

       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "false" ) );

       if( selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "true" ) );


       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       selenium.click( "deactivated_btn" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "deactivated_btn" )
       );

       selenium.click( "btn_1" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "btn_1" )
       );

       selenium.click( "btn_2" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getText( "btn_2" )
       );

       selenium.select( "single_list" , "Option 2" );
       assertEquals( 
            selenium.getSelectedLabel( "single_list" ),
            "Option 2"
       );

       selenium.select( "multi_list" , "Multi Option 2" );
       selenium.addSelection( "multi_list" , "Multi Option 3" );
       String[] selectedOpts = selenium.getSelectedLabels( "multi_list" );
       assertEquals( 
            selectedOpts[0], 
            "Multi Option 2"
       );
       assertEquals( 
            selectedOpts[1],
            "Multi Option 3"
       );

       selenium.stop();
       setUp("c:\\index.htm", "*chrome");
       selenium.open("c:\\index.htm");
       selenium.type( "file_field" , "Some Text" );
       assertEquals(
            selenium.getValue( "file_field" ),
            "Some Text"
       );
       selenium.stop();
       setUp("c:\\index.htm", "*firefox");
       selenium.open("c:\\index.htm");

       selenium.click( "alert_btn" );
       assertTrue( selenium.isAlertPresent() );
       assertEquals( selenium.getAlert(), "This is Alert" );

       selenium.click( "conf_btn" );
       assertTrue( selenium.isConfirmationPresent() );
       selenium.chooseOkOnNextConfirmation();
       assertEquals( selenium.getConfirmation(), "This is confirmation" );
 }

}{/syntaxhighlighter}

И последний шаг: обработать prompt-диалог. По функционалу данный тип диалога соответствует confirmation-диалогу за исключением того, что еще нужно вводить текст. Это отражено в методах Selenium-a. В частности, для выбора кнопки, которую нужно нажать, по-прежнему используются методы chooseOkNoNextConfirmation и chooseOkOnNextConfirmation. В дополнение к этому, текст, вводимый в prompt-диалог задается методом answerOnNextPrompt, в котором указывается вводимая строка.

Используя данную информацию, реализуем последний шаг:

{syntaxhighlighter brush: java;fontsize: 100; first-line: 1; highlight: [107,108,109,110,111]; }package com.example.tests;
import com.thoughtworks.selenium.*;

import java.util.regex.Pattern;

public class NewTest extends SeleneseTestCase {

  public void setUp() throws Exception {
    setUp("c:\\index.htm", "*firefox");
  }

  public void testNew() throws Exception {
       selenium.open("c:\\index.htm");
       selenium.type("text_field" , "Sample Text" );
       assertEquals( selenium.getValue( "text_field" ) , "Sample Text" );
       selenium.type("text_area" , "Sample Text" );
       assertEquals( selenium.getValue( "text_area" ) , "Sample Text" );

       selenium.click( "radio_2" ); // Select item via click
       assertTrue( selenium.isChecked( "radio_2" ) );
       selenium.check( "radio_1" ); // Select item via check
       assertTrue( selenium.isChecked( "radio_1" ) );

       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );
       selenium.check( "check_box" );
       assertTrue( selenium.isChecked( "check_box" ) );

       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "false" ) );

       if( selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       assertTrue( selenium.getEval( "var win = selenium.browserbot.getCurrentWindow();" +
                "var element = win.getElementById('deactivated_btn',win);" +
                "element.disabled;" ).toLower().equals( "true" ) );


       if( !selenium.isChecked( "ev_check_box" ) ){
             selenium.click( "ev_check_box" ); // Set check mark initiating onclick event
       }

       selenium.click( "deactivated_btn" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "deactivated_btn" )
       );

       selenium.click( "btn_1" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getValue( "btn_1" )
       );

       selenium.click( "btn_2" );
       assertEquals( 
            selenium.getText( "clicked_text" ),
            selenium.getText( "btn_2" )
       );

       selenium.select( "single_list" , "Option 2" );
       assertEquals( 
            selenium.getSelectedLabel( "single_list" ),
            "Option 2"
       );

       selenium.select( "multi_list" , "Multi Option 2" );
       selenium.addSelection( "multi_list" , "Multi Option 3" );
       String[] selectedOpts = selenium.getSelectedLabels( "multi_list" );
       assertEquals( 
            selectedOpts[0], 
            "Multi Option 2"
       );
       assertEquals( 
            selectedOpts[1],
            "Multi Option 3"
       );

       selenium.stop();
       setUp("c:\\index.htm", "*chrome");
       selenium.open("c:\\index.htm");
       selenium.type( "file_field" , "Some Text" );
       assertEquals(
            selenium.getValue( "file_field" ),
            "Some Text"
       );
       selenium.stop();
       setUp("c:\\index.htm", "*firefox");
       selenium.open("c:\\index.htm");

       selenium.click( "alert_btn" );
       assertTrue( selenium.isAlertPresent() );
       assertEquals( selenium.getAlert(), "This is Alert" );

       selenium.click( "conf_btn" );
       selenium.chooseOkOnNextConfirmation();
       assertTrue( selenium.isConfirmationPresent() );
       assertEquals( selenium.getConfirmation(), "This is confirmation" );

       selenium.click( "prompt_btn" );
       selenium.chooseOkOnNextConfirmation();
       selenium.answerOnNextPrompt( "Some answer" );
       assertTrue( selenium.isPromptPresent() );
       selenium.getPrompt();
 }

}{/syntaxhighlighter}

Вот основные случаи работы со стандартными диалогами сообщений.

И еще один момент. Как было указано ранее, Selenium самостоятельно обрабатывает стандартные диалоги, так что они появляться не должны. Но данная обработка происходит после того как страница загрузилась полностью. Если же диалог появился до завершения загрузки, то Selenium данную ситуацию может не перехватить (в частности, если диалог появляется при работе обработчика события onload). Подобная ситуация приводит к заклиниванию выполнения теста и данную ситуацию средствами Selenium-a не отследить. Соответственно, подобные ситуации лучше обходить при первой же возможности. Лучше недопроверить один UI-функционал, но покрыть тестами сотни других функционалов.

Подведем итог:

  • При работе с окнами сообщений стоит придерживаться следующей последовательности действий: выявить факт появления диалога, предварительно задать кнопку для нажатия и вводимы текст (там, гле надо, естественно), извлечь сообщение.
  • Для обнаружения диалога используются методы isAlertPresent, isConfirmationPresent, isPromptPresent
  • Кнопка для нажатия задается методами chooseOkOnNextConfirmation и chooseCancelOnNextConfirmation. Эти методы применимы для confirmation- и prompt-диалогов
  • Для задания вводимого в prompt-диалог текста используется метод answerOnNextPrompt
  • Извлечение текста сообщения с последующим выполнением "заказанных" действий (нажатие кнопки и ввод текста) выполняется методами getAlert, getConfirmation, getPrompt в зависимости от типа диалога, который появился

Продолжение следует...

Часть 1Часть 3


(Automation) #2

To KaNoN: Ну ты хоть сам понял, что ты написал ?

 

 

Итак, нам нужно перейти в *chrome-режим, открыть страницу и ввести текст. Как-то так:

 

 

 

 com.example.tests; com.thoughtworks.selenium.*; java.util.regex.Pattern; class NewTest extends SeleneseTestCase {public void setUp() throws Exception {setUp("c:\\index.htm""*firefox");}public void testNew() throws Exception {selenium.open("c:\\index.htm");selenium.type("text_field" "Sample Text" );assertEquals( selenium.getValue( "text_field" ) , "Sample Text" );selenium.type("text_area" "Sample Text" );assertEquals( selenium.getValue( "text_area" ) , "Sample Text" );selenium.click( "radio_2" ); // Select item via clickassertTrue( selenium.isChecked( "radio_2" ) );selenium.check( "radio_1" ); // Select item via checkassertTrue( selenium.isChecked( "radio_1" ) );selenium.check( "check_box" );assertTrue( selenium.isChecked( "check_box" ) );selenium.check( "check_box" );assertTrue( selenium.isChecked( "check_box" ) );



(Mykhailo Poliarush) #3

Если есть желание критиковать, то пожалуйста, прошу писать конструктивную критику (критика по делу). Нужно рассписать что это такое? 
Потому как данное данные высказывания, ровным образом ничего не стоят, чисто из-за того что не указано в чем собственно состоит ошибка/недочет автора.


(Testing Man) #4

у меня такой вопрос если алерт автоматически вспливает и через несколко секунд автоматически уходит но мне надо в тесте проверит если это окно поивилось?
я исползую :selenium + java вес тест делаю динами .
например сравннение текста я сделал так:

case "VALIDATETEXT":
actualData = driver.findElement(
this.getObject(m, objectName, objectType)).getText();
if (cellData.trim().equals(actualData.trim())) {
	System.out.println("ok");
	return true;`

Thanks!