TestNG - Фабрики и поставщики данных - PullRequest
2 голосов
/ 01 июня 2010

История вопроса

Я работаю в компании по разработке программного обеспечения, которая разрабатывает среду автоматизации тестирования, чтобы заменить нашу старую запутанную систему спагетти.

Поскольку наша система требует входа в систему практически для всего, что мы делаем,Я решил, что будет лучше использовать @BeforeMethod, @DataProvider и @Factory для настройки моих тестов.Однако я столкнулся с некоторыми проблемами.

Пример теста

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

(Примечание: я знаю, что BeforeMethods не запускаются в любом заданном порядке - предположим, что об этом позаботились длясейчас.)

@BeforeMethod
public void setupSelenium() {
    // login with username & password
    // acknowledge announcements
    // navigate to search page
}

@Test(dataProvider="players")
public void testSearch(String playerName, String searchTerm) {
    // search for "searchTerm"
    // browse through results
        // pass if we find playerName
    // fail (Didn't find the player)
}

Этот тестовый пример предполагает следующее:

  • Пользователь уже вошел в систему (скорее всего, в BeforeMethod)
  • Пользовательуже перешел на страницу поиска (тривиально, перед методом)
  • Параметры теста связаны с вышеупомянутым логином

Проблемы

Итак, давайте попробуеми выяснить, как обрабатывать параметры для тестового примера.

Idea # 1

Этот метод позволяет нам связывать поставщики данных с именами пользователей и позволяет использовать несколько пользователейдля любого конкретного теста!

@Test(dataProvider="players")
public void testSearch(String user, String pass, String name, String search) {
    // login with user/pass
    // acknowledge announcements
    // navigate to search page
    // ...
}

... но есть много повторений, так как мы должны заставить КАЖДУЮ функцию принимать два дополнительных параметра.Не говоря уже о том, что мы также тестируем функцию уведомлений о подтверждении, которую мы на самом деле не хотим тестировать.

Idea # 2

Итак, давайте воспользуемся фабрикойчтобы правильно инициализировать вещи!

class BaseTestCase {

    public BaseTestCase(String user, String password, Object[][] data);

}

class SomeTest {

    @Factory
    public void ...

}

Таким образом, мы заканчиваем тем, что пишем по одной фабрике на тестовый случай ... Хотя, это позволяет нам иметь несколько пользователей на тестовый случай.

Заключение

Я о свежих идеях.У меня была другая идея, когда я загружал данные из файла XML, а затем вызывал методы из программы ... но это глупо.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 02 июня 2010

Я все еще не уверен, что понимаю вашу проблему ...

Вас не устраивает ваша вторая попытка, т. Е. Необходимость писать @Factory для каждого теста? Тогда почему бы не поместить аннотацию @Factory в конструктор базового класса? Таким образом, все, что нужно сделать вашим подклассам - это вызвать super, и все готово.

Чего именно вы пытаетесь достичь?

2 голосов
/ 01 июня 2010

Во-первых, кажется, что вы пытаетесь сделать слишком много в каждом тестовом примере. Например, если вы ищете что-то, зачем вам нужно проверять навигацию как часть поиска?

Во-вторых, кажется, что ваши требования неясны. Можете ли вы создать тест, в котором вы отправите ему один поисковый запрос и получите один результат? Похоже, это должен быть твой первый тест.

В-третьих, почему авторизованное сеансовое соединение / объект не может быть требованием для теста? Судя по вашему коду, похоже, что вы делаете какой-то вызов через HTTP. Даже если это не так, похоже, вы используете какого-то брокера для отправки сообщения в ваше приложение, учитывая, что вам приходится передавать имя пользователя и передавать каждый запрос ... Почему бы просто не автоматизировать весь вещь в объекте «авторизованный брокер», который позволяет отправить запрос по предварительно авторизованному соединению?

Затем просто отправьте авторизованного брокера в свои тесты, чтобы обработать передачу сообщений. Или, что еще лучше, настройте своего авторизованного брокера в функциях предварительного тестирования (BeforeMethods?) И сделайте его доступным как переменная члена класса.

1 голос
/ 03 июня 2010

Cederic,

Я должен был создать аккаунт с первого дня, я больше не могу редактировать свое старое сообщение или отвечать на комментарии (на данный момент). Позвольте мне немного расширить это.

Вот пример того, что я придумал до сих пор. Наверное, я ответил на свой вопрос ... это работает, но немного неприятно.

Мой вопрос сейчас, у меня все тесты на одном заводе. Это не хорошо по нескольким причинам. Во-первых, я должен добавить их все вручную (или поместить их в задумчиво). Во-вторых, я должен запустить все по существу как один пакет. Есть идеи?

package example2;

import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.annotations.*;

public class WebTestBase {

  protected String host, username, password;
  protected HashMap<String, Object[][]> dataSet;

  public WebTestBase(String host, String username, String password, HashMap<String, Object[][]> dataSet) {
    this.host = host;
    this.username = username;
    this.password = password;
    this.dataSet = dataSet;
  }

  @DataProvider(name="dataSet")
  public Object[][] dataSet(Method m) {
    return dataSet.get(m.getName());
  }

  @BeforeMethod
  public void login() {
    System.out.println("Logging in to " + host + " with " + username + ":" + password);
  }

  @AfterMethod
  public void logout() {
    System.out.println("Logging out!");
  }
}

package example2;

import java.util.HashMap;

import org.testng.annotations.Factory;

public class WebTestFactory {
  @Factory
  public Object[] factory() {
    HashMap<String, Object[][]> dataSetOne = new HashMap<String, Object[][]>();
    dataSetOne.put("searchRoster", new Object[][] {
          {"mcguire", "McGuire, Mark"},
          {"ruth", "Ruth, Babe"}
        });

    HashMap<String, Object[][]> dataSetTwo = new HashMap<String, Object[][]>();
    dataSetTwo.put("addPlayer", new Object[][] {
          {"Sammy Sosa", 0.273}
        });

    Object[] tests = new Object[] { 
        new SearchTest("localhost", "user", "pass", dataSetOne),
        new AddTest("localhost", "user", "pass", dataSetTwo)
      };

    return tests;
  }
}

package example2;

import java.util.HashMap;
import org.testng.annotations.Test;

public class SearchTest extends WebTestBase {

  public SearchTest(String host, String username, String password,
      HashMap<String, Object[][]> dataSet) {
    super(host, username, password, dataSet);
  }

  @Test(dataProvider="dataSet")
  public void searchRoster(String searchTerm, String playerName) {
    System.out.println("Searching for " + searchTerm);
    System.out.println("I found " + playerName + " in the search results!");
  }

}

package example2;

import java.util.HashMap;

import org.testng.annotations.Test;

public class AddTest extends WebTestBase {

  public AddTest(String host, String username, String password,
      HashMap<String, Object[][]> dataSet) {
    super(host, username, password, dataSet);
  }

  @Test(dataProvider="dataSet")
  public void addPlayer(String playerName, double battingAvg) {
    System.out.println("Adding " + playerName + " with avg " + battingAvg);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...