Покажите пожалуйста пример с data driven testing

Читаю книгу и наткнулся на такой подход в Selenium Webdriver как data driven testing. Можете показать на просто примере использование этого подхода?

Только просьба дать пример с jUnit

http://g.zeos.in/?q=data%20driven%20testing%20examples%20junit

3 лайка

4 or 5? Могу Cucumber показать.

junit 4
а вот куумбер я еще не учил, можно на чистом селениуме?

1 лайк

на ютюбе не пробовли искать - так там полно https://www.youtube.com/results?search_query=selenium+data+driven+testing+junit

Selenium это тупо фрейм для имитации действий юзера в браузере. ВСЁ.
Нужен какой-нибудь runner (junit, testng, cucumber), либо пишите свой на чистом языке Java/Scala, etc.

И что? Как это относится к моему вопросу?

Есть 3 подхода это:

  1. DDT (Data Driven Testing) - этот подход реализуется с помощью TestNG, JUnit и другими.
  2. BDD (Behaviour Driven Development) - этот подход реализуется с помощью Cucumber, JBehave
  3. KDT (Keyword-driven testing) - этот подход реализуется с помощью Robot Framework

Я написал только те фреймворки, которые знаю. А то что ты просишь показать пример, так это берешь и гуглишь определенный фреймворк и разбираешь его, в двух словах так не рассказать, как работает каждый фреймворк.

1 лайк

Уважаемый вы что то путаете, а как же examples в BDD? Это самый настоящий DDT подход.

Есть такая коллекция

    @Parameterized.Parameters
    public static Collection testData() {
        return Arrays.asList(new Object[][] {
                { "Testeruser1",  "email1@email.com", "password" },
                { "Testeruser2",  "email2@email.com", "password" },
                { "Testeruser3",  "email3@email.com", "password" },
                { "Testeruser4",  "email4@email.com", "password" } });
    }

Как фреймворк понимает, что Testeruser1 надо вставить именно в поле USERNAME, email1@email.com в поле EMAIL, password в поле PASSWORD?
Можете на этот вопрос ответить? Потому что по коду, который я запустил нет никакой связи между полями и этими данными с коллекции.
Например

WebElement fname = driver.findElement(By.xpath("//*[@id=\"user[login]\"]"));
        fname.click();
        fname.clear();
        fname.sendKeys(username);

        WebElement emailAddress = driver.findElement(By.xpath("//*[@id=\"user[email]\"]"));
        emailAddress.click();
        emailAddress.clear();
        emailAddress.sendKeys(email);

        WebElement pass = driver.findElement(By.xpath("//*[@id=\"user[password]\"]"));
        pass.click();
        pass.clear();
        pass.sendKeys(password);

Через рефлексию. Фреймворк знает о классе с тестами (это мы ему говорим при старте), знает что класс параметризирован (об этом мы сказали используя аннотацию класса Parametrized), и знает что для этого конкретного класса нужно использовать метод testData() в качестве источника данных (это он узнает с помощью аннотации Parametrized.Parameters над методом).
Во время выполнения фреймворк делает следующее:

  1. Находит метод с аннотацией Parametrized.Parameters и вызывает его. В Вашем случает - это метод testData(). Таким образом фреймворк получает массив с массивами данных. Вызов допустим без создания инстанса, так как метод статический.
  2. Для каждого элемента внешнего массива создает объект тестового класса, вызывая его конструктор рефлективно и передавая в качестве аргументов все элементы внутреннего массива. Также возможен вариант создания объекта через конструктор без аргументов и последующей установкой полей. Опять же, это тоже происходит рефлективно. В обоих случаях - в результате будет создан объект тестового класса с инициализированными полями.
  3. Находит методы с аннотацией Test и вызывает их. Тоже рефлективно.

JUnit - это open-source инструмент, Вы можете посмотреть как все это работает скачав его исходники.
Очень-очень упрощенно идея “пускателя тестов” реализована вот тут.

1 лайк

Поясните пожалуйста рефлективно что значит?
Но вот скажем есть такие данные

                { "Testeruser1",  "email1@email.com", "password" },
                { "Testeruser2",  "email2@email.com", "password" },
                { "Testeruser3",  "email3@email.com", "password" },
                { "Testeruser4",  "email4@email.com", "password" } });

Как фреймворк понимает, что Testeruser1 идет в поле USERNAME, а например не в поле EMAIL? Я не вижу вообще связи между этим

Ваш тестовый класс помечен аннотацией @RunWith(Parameterized.class)
Раннер знает, что в таком классе должен быть статический метод - провайдер данных. Вы его приводили уже:

@Parameterized.Parameters
public static Collection testData() {
...

Из кода видно, что возвращается Arrays.asList(new Object[][] ... т.е. двумерный массив объектов возвращается как коллекция (список списков). Кажадя строка этой коллекции - отдельный набор данных для теста. Этот метод - ваш провайдер набора тестовых данных. Как уже Вам написали выше, рефлексиво эти данные раннером помещаются в конструктор тестового класса столько раз, сколько строк в вашем двумерном массиве данных.

Посмотрите на конструктор вашего тестового класса. Вероятнее всего в него передается три строковых параметра, вот в первый из них попадет "Testeruser1", во второй - "email1@email.com", а в третий - "password". Это и будет набор для первого кейса.

UPD: По поводу рефлексии (статья на вики). Если совсем просто: раннер JUnit анализирует скомпилированный код и, в зависимости от аннотаций, знает что делать с конкретным методом или классом. Но Вам все же стоит почитать какой-нибудь мануал по JUnit, иначе вопросы будут возникать практически постоянно

Java Reflection API - инструменты, позволяющие узнавать информацию о методах/полях класса во время выполнения программы. Trail: The Reflection API (The Java™ Tutorials)

Но для начала рекомедую не разбираться с этим, а поучить Java с самого начала, понять зачем вообще она была создана и как работает.

1 лайк

То есть я правильно понял, что если я добавлю еще тестовые данные через запятую - так

{ "Testeruser1",  "email1@email.com", "password", "secretQuestion" },

то secretQuestion просто будет игнортроваться, так как в конструкторе всего три параметра, а четвертого нет, верно?

Да, правильно. Если Вам нужен еще один параметер, то нужно добавить член класса, куда вы будете его сохранять и, соответственно, инжектировать его через конструктор.

1 лайк

Хотя скорее всего, у вас должно возникнуть исключение. Т.к. конструктор ожидает три параметра, а вы пытаетесь передать 4

2 лайка

Предполагаю что он игнорироваться не будет: не забывайте что я написал выше о том как JUnit создает объект тестового класса. Что будет если у Вас в конструкторе 3 аргумента, а Вы пытаетесь вызвать его с 4-мя?.. Верно, это даже не скомпилируется. Но так как JUnit работает через рефлексию - то во время компиляции еще неизвестно, будет ли корректно вызван конструктор, и компиляция пройдет нормально. Зато во время выполнения это приведет к ошибке.

Так что будьте внимательны. Если у конструктора 3 аргумента - то и параметров должно быть три.

1 лайк