Про Тестинг: обеспечение качества, тестирование, автоматизация

Раздел: Автоматизация > Практикум > PageObjects pattern + Selenium (Java)

PageObjects pattern + Selenium (Java)

Попробуем на небольшом примере показать как, используя PageObjects pattern и Selenium (Java), можно достаточно быстро реализовать фреймоворк для автоматизированного тестирования, и начать писать понятные, легко поддерживаемые, а главное работающие тесты.

Рассмотрим пример реализованный на базе Selenium RC. (Реализация для Selenium 2 (WebDriver) выполняется по аналогии. Если у вас возникнут вопросы, обращайтесь - поможем)

Пример:

Страница LoginPage состоит из двух полей ввода User и Password, кнопки Login. При отправке корректного логина и пароля открывается страница Home на которой есть имя пользователя и ссылка Logout. При отправке НЕкорректного логина и пароля открывается страница ErrorLogin, на которой есть сообщение об ошибке и ссылка Back To Login Page.

Задание:

Написать тестовые скрипты:
1. Корректный Login -> проверка имени пользователя -> Logout
2. Некорректный Login -> проверка сообщения об ошибке -> Back To Login Page

Решение:

1. Создаем рабочий контекст на базе Selenium 1.x.x

Context.java:
public class Context {
    public static final String BROWSER_IE = "*iexplore";
    public static final String BROWSER_FF = "*firefox";
    public static final String BROWSER_CH = "*chrome";
    private static Context context;
    private static String siteUrl;
    private Selenium browser;
    private SeleniumServer seleniumServer;
    private Context() {
    }
    public static void initInstance(String browserType, String siteURL) {
        context = new Context();
        siteUrl = siteURL;
        context.setBrowser(new DefaultSelenium("localhost", 4444, browserType, siteURL));
        context.start();
    }
    public static Context getInstance() {
        if (context == null) {
            throw new IllegalStateException("Context is not initialized");
        }
        return context;
    }
    public Selenium getBrowser() {
        if (browser != null) {
            return browser;
        }
        throw new IllegalStateException("WebBrowser is not initialized");
    }
    public String getSiteUrl() {
       return siteUrl;
    }
    public void start() {
        try {
            seleniumServer = new SeleniumServer();
            seleniumServer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        browser.start();
    }
    public void close() {
        browser.close();
        browser.stop();
        seleniumServer.stop();
    }
    public void setBrowser(Selenium browser) {
        this.browser = browser;
    }
}

2. Добавляем в абстрактный супер класс Page ссылку на рабочий контекст context, а также сервисный метод для получения из него объекта Selenium getBrowser().

Page.java:
public abstract class Page {
    private Context context;
    private String currentPage;
    protected Page(String pageUrl) {
        this.currentPage = pageUrl;
        setContext(Context.getInstance());
        init();
        parsePage();
    }
    private void setContext(Context instance) {
        this.context = instance;
    }
    protected abstract void init();
    protected abstract void parsePage();
    public String getCurrentPage() {
        return context.getSiteUrl() + this.currentPage;
    }
    protected Selenium getBrowser() {
        return context.getBrowser();
    }
    // ....
    // service methods...
    // ....
}

3. Реализуем классы страниц, необходимые при написании тестов для нашего примера, а именно: LoginPage, HomePage и ErrorLoginPage. И добавляем в сервисные методы реальный ввод данных в поля, нажатие кнопок и клики на ссылки

LoginPage.java:
public class LoginPage extends Page {
   public static final String PAGE_URL = "/login.html";
   protected LoginPage() {
       super(PAGE_URL);
   }
   public static LoginPage openLoginPage() {
       LoginPage loginPage = new LoginPage();
       loginPage.getBrowser().open(PAGE_URL);
       return loginPage;
   }
   private void setUserName(String userName) {
       // код для заполнения поля Username
       getBrowser().type("id=UserName", userName);
   }
   private void setPassword(String password) {
       // код для заполнения поля Password
       getBrowser().type("id=Password", password);
   }
   private void pushLoginButton() {
       // код для нажатия на кнопку Login
       getBrowser().click("id=LoginButton");
   }
   protected void parsePage() {
       // Разбор элементов страницы
       // Заполнение необходимых переменных данными со страницы
   }
   protected void init() {
       // Инициализация страницы, например проверка адреса (URL) страницы:
       if(!getBrowser().getLocation().equals(PAGE_URL)) {
           throw new IllegalStateException("Invalid page is opened");
       }
       // Можно также добавить проверки наличия необходимых для дальнейшей работы
       // объектов и т.д.
   }
   private void loginAs(String userName, String password) {
       setUserName(userName);
       setPassword(password);
       pushLoginButton();
   }
   public HomePage login(String userName, String password) {
       loginAs(userName, password);
       return new HomePage();
   }
   public ErrorLoginPage loginInvalid(String userName, String password) {
       loginAs(userName, password);
       return new ErrorLoginPage();
   }
}
HomePage.java:
public class HomePage extends Page {
   public static final String PAGE_URL = "/home.html";
   private String loggedinUserName;
   protected HomePage() {
       super(PAGE_URL);
   }
   protected void init() {
       // Инициализация страницы
   }
   protected void parsePage() {
       // Разбор элементов страницы
       this.loggedinUserName = getBrowser().getText("id=userName");
   }
   public String getLoggedinUserName() {
       return loggedinUserName;
   }
   public LoginPage logout() {
       getBrowser().click("id=LogoutLink");
       return new LoginPage();
   }
}
ErrorLoginPage.java:
public class ErrorLoginPage extends Page {
   public static final String PAGE_URL = "/loginError.html";
   private String errorMessage;
   protected ErrorLoginPage() {
       super(PAGE_URL);
   }
   protected void init() {
       // Инициализация страницы
   }
   protected void parsePage() {
       // Разбор элементов страницы
       this.errorMessage = getBrowser().getText("id=ErrorMessage");
   }
   public String getErrorMessage() {
       return this.errorMessage;
   }
   public LoginPage backToLoginPage() {
       getBrowser().click("id=BackLink");
       return new LoginPage();
   }
}

4. Пишем тесты на базе JUnit:

public class TestLogin extends TestCase {
   public void setUp() {
        // Инициализация контекста.
        Context.initInstance(Context.BROWSER_IE, "http://www.testtesttestlogin.com");
    }
   public void testLoginLogout() {
        String userName = "tester";
        String password = "testPass";
        LoginPage loginPage = LoginPage.openLoginPage();
        HomePage homePage = loginPage.login(userName, password);
        assertEquals(userName, homePage.getLoggedinUserName());
        homePage.logout();
    }
    public void testInvalidLogin() {
        String userName = "$tester@#";
        String password = "********";
        String expectedMessage = "Invalid username or password";
        LoginPage loginPage = LoginPage.openLoginPage();
        ErrorLoginPage errorLoginPage = loginPage.loginInvalid(userName, password);
        assertEquals(expectedMessage, errorLoginPage.getErrorMessage());
        errorLoginPage.backToLoginPage();
    }
    protected void tearDown() throws Exception {
        // закрытие браузера
       Context.getInstance().close();
    }
}

Скачать исходный код примера реализации Page Object Pattern на базе Selenium RC

Вот все и готово - первые объекты страниц, первые тесты. Попробуйте, может и Вам подойдет подобная архитектура. В любом случае всегда все можно обсудить - любые комментарии с вопросами и конструктивной критикой приветствуются. Вопросы “отвечаются” быстро, критика анализируется... :)

Смотрите также Автоматизированное тестирование: работа со статическими ресурсами


Автор: Алексей Булат

Наверх