Как написать простейший тест на Thucydides, пособие для новичка

В поддержку новой инициативы - мега склад примеров на github
Создаем примеры по автоматизации вместе, просто присылайте pull requrest
А также инициативы создания at.info code recipes

Всем привет, в предисловии к Как настроить Jenkins+Thucydides Unix-based OS + Maven

Создадим небольшой тестик (весь код проекта можно скачать из мега-склада на github):

на текущий момент я использую такую сборку: Selenium+Java+IntellijIdea+JUnit+Maven+Thucydides+Jenkins

Нам понадобится следующие классы:

  1. GoogleNavigationAndSearch - Main
    import net.thucydides.core.annotations.*;
    import net.thucydides.core.pages.Pages;
    import net.thucydides.junit.annotations.Concurrent;
    import net.thucydides.junit.runners.ThucydidesRunner;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.openqa.selenium.WebDriver;
    
    import java.util.Properties;
    
    @Story(Application.Register.Booking.class)
    @RunWith(ThucydidesRunner.class)
    @Concurrent(threads="1")
    public class GoogleNavigationAndSearch
    {
        public Properties keyWords;
        {
            keyWords = PropertiesReader.readProperties("Google.properties");  // Подгружаем файл с данными
        }
    
        @Managed(uniqueSession = true)
        private WebDriver driver;
    
        @Before
        public void myTest()  throws Exception
        {
            System.setProperty("webdriver.chrome.driver", "/home/rb/Downloads/chromedriver"); // Путь для хромдрайвера
            driver.manage().window().maximize();
        }
    
        @After
        public void close()
        {
            driver.close();
        }
    
        @ManagedPages(defaultUrl = "http://google.com/")
        public Pages pages;
    
        @Steps
        public GoogleNavigation google;
    
       // @WithDriver("chrome")
        @WithTag("googleSearch")
        @Test
        public void GuestBooking() throws InterruptedException
        {
            google.start_browser();
            google.input_search_query(keyWords.getProperty("searchQuery"));
            google.click_to_submit_search_query();
            Thread.sleep(15000);
        }
    }

  1. GoogleNavigation - Steps

     import net.thucydides.core.annotations.Step;
        import net.thucydides.core.pages.Pages;
        import net.thucydides.core.steps.ScenarioSteps;
        
        public class GoogleNavigation extends ScenarioSteps
        {
            Google google;
            public GoogleNavigation(Pages pages)
            {
                super(pages);
            }
        
            @Step
            public void start_browser()
            {
                Google loginPage = getPages().get(Google.class);
                loginPage.open();
            }
        
            @Step
            public void input_search_query(String searchQuery)
            {
                google.setInputField(searchQuery);
            }
        
            @Step
            public void click_to_submit_search_query() throws InterruptedException
            {
                google.setSubmitSearch();
            }
        }

  1. Google - класс для поиска элементов

    import net.thucydides.core.pages.PageObject;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    
    public class Google extends PageObject
    {
        private static final Integer CATALOG_WAIT_FOR_TIMEOUT = 20000;
    
        public Google(WebDriver driver) {
            super(driver, CATALOG_WAIT_FOR_TIMEOUT);
        }
    
        @FindBy(name = "q")
        private WebElement inputField;
    
        public void setInputField(String searchQuery)
        {
            element(inputField).type(searchQuery);
        }
    
        @FindBy(xpath = "//div/div[3]/div[1]/div[1]/div[3]/div/div/div/form/div[1]/button")
        @FindBy(id = "gbqfb")
        private WebElement submitSearch;
    
        public void setSubmitSearch() throws InterruptedException
        {
            element(submitSearch).click();
        }
    }
  1. Application - //Указываем Story для тестов относительно нее будет сформирован отчет
import net.thucydides.core.annotations.Feature;
    
    public class Application
    {
        @Feature
        public class Register
        {
            public class Booking{}
        }
    }
  1. PropertiesReader - класс необходимый для подгрузки файлов (e.g. Google.properties)
    import java.io.*;
    import java.util.Properties;
    
    
    public class PropertiesReader
    {
    
        public static Properties readProperties(String name)
        {
            Properties properties = new Properties();
            InputStream stream = null;
            try
            {
                stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
                properties.load(stream);
            }
            catch (IOException e)
            {
    
                e.printStackTrace();
    
            } finally
            {
                if (stream != null)
                {
                    try
                    {
                        stream.close();
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
    
                    }
                }
            }
            return properties;
        }
    }
  1. Google.properties - Ну и сам файлик с данными
    searchQuery = testing
  1. POM

В данному примере мы рассматривали обычную работу с гуглом:

  1. Запуск браузера - google.start_browser();
  2. Вписываем в поле ввода запрос - google.input_search_query(keyWords.getProperty(“searchQuery”));
  3. Нажимаем кнопку для подтверждение запроса - google.click_to_submit_search_query();
  4. Ждём, чтобы убедиться визуально, что всё хорошо :slight_smile: - Thread.sleep(15000);

Весь код проекта можно найти и скачать из мега-склада на github

Пусть таких примеров станет больше, присылайте pull request на наш мега-склад примеров.

2 лайка

@Beliy_Ruslan спасибо за пост! Я немного подправил :pencil2: раскраску кода.

Если блок кода заключить в 3 обратные кавычки, то он красивее раскрашивается:

спасибо :smile: буду знать :slight_smile:

1 лайк

Спасибо за пример!
Непросто с помощью Thucydides написать даже такой простенький тест. Ссылка в тему: Bullshit driven development - Андрей Солнцев — ЖЖ

1 лайк

просто)) будут вопросы - пиши)

Кажется анотация @Concurrent используется только дата драйвен тест ранера ThucydidesParameterizedRunner.class Для обычного ранера политика потоков разруливается иначе.
Поправьте если я не прав.

А это зачем, если можно через командную строку мевена передавать:
-Dwebdriver.driver=chrome
Или есть какие-то определенные условия, по которым нужно задавать путь к хром драйверу, вместо того что бы просто прописать путь до него в системную переменную PATH?

Или если запускаете из IDE и нужно отлаживать на разных драйверах то можно просто дописать:

@Managed(uniqueSession = true, driver="chrome")
        private WebDriver driver;

Ненужно же вроде. Сам закрывается

Каждый раз когда Вы используете трид слип - в мире умирает один единорог :frowning:

Зачем в вашем пом файле оно повторяется два раза?

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

@Managed(uniqueSession = true, driver="chrome")
        private WebDriver driver;
FAILED TO CREATE NEW DRIVER INSTANCE class org.openqa.selenium.chrome.ChromeDriver

Системной переменной у меня отдельный случай :slight_smile: Долго рассказывать :slight_smile:

  1. Хром частенько зависает в процессах, особенно на Win. По-этому лучше лишний раз закрывать.

  2. Thread.sleep(15000); - сам плачу) для примера описывал, чтобы было видно визуально, что всё прошло успешно))

  3. Да, упустил этот нюанс в депенденси

@heartwilltell я бы предложил тебе создать свой пример, более усовершенствованный и положить в наш мега склад на github или может быть поделиться какими-то другими наработками по Thucydides

Не, спасибо, мы уж как-нибудь простыми и надёжными средствами, без монстров.

1 лайк

Каждый раз, когда кто-то использует сусидидис - в мире умирает один котик

1 лайк

С чего бы это? Хороший же фреймворк, есть конечно свои сложности, но где их нет то?

1 лайк

В данном случае сложностей слишком много (одно только оглавление мануала занимает 30 страниц!), но главное, что эти сложности неоправданы - с помощью них не решаются никакие реальных проблем.