Проектирование DSL для веб-тестирования, реализуемого различными драйверами для веб-тестирования — должны ли мы смешивать примитивные и непримитивные операции?

Мы реализуем проект автоматизации веб-тестирования для некоторых интранет-приложений.

Чтобы упростить написание каждого теста, мы разрабатываем Java DSL, который может быть реализован с использованием различных адаптеров (до сих пор мы выбрали Sahi и Selenium/WebDriver, так как хотим сравнить их вместе с точки зрения производительности, удобочитаемости, ремонтопригодность и др.).

Мы определили два типа операций в DSL:

1) Примитивный: его реализация, безусловно, должна иметь дело со спецификой HTML/Selenium/Sahi/и т. д. Пример: (с использованием веб-драйвера Sahi)

public void insertProjectRecord(String projectName) {
  b.link("Create new project").click();
  b.textbox("ctl00$ProjectForm$Name").setValue(projectName);
  b.span("Insert").click();
}

2) Non-Primitive: операция, которую стоит включить в наш DSL в целях повторного использования, хотя ее можно построить с использованием примитивов. Пример:

public void createFormulation(String projectName, String rteDummyText) {
  goToAddProjectPage();
  insertProjectRecord(projectName);
  switchToEditModeForFirstAvailableRecord();
  editBeneficiaryCountries();
  editAcronyms(rteDummyText);
  saveSectionChanges();
}

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

Какой другой подход вы бы предложили и/или рассмотрели?


person Sebastian    schedule 24.08.2010    source источник


Ответы (1)


Я настоятельно рекомендую использовать объектную модель страницы. В этом вы создаете класс для каждой страницы, а затем абстрагируете элементы.

Я написал сообщение в блоге о написании поддерживаемых тестов здесь . Вы можете увидеть мою запись в блоге об объектной модели страницы здесь

Таким образом, ваш объект может быть таким, как показано ниже.

public class Home
{
    private readonly ISelenium _selenium;

    /// <summary>
    /// Instantiates a new Home Page object. Pass in the Selenium object created in the test SetUp(). 
    /// When the object in instantiated it will navigate to the root
    /// </summary>
    /// <param name="selenium">Selenium Object created in the tests
    public Home(ISelenium selenium)
    {
        this._selenium = selenium;
        if (!selenium.GetTitle().Contains("home"))
        {
            selenium.Open("/");
        }
    }

    /// <summary>
    /// Navigates to Selenium Tutorials Page. Selenium object wll be passed through
    /// </summary>
    /// <returns>SeleniumTutorials representing the selenium_training.htm</returns>
    public SeleniumTutorials ClickSelenium()
    {
        _selenium.Click("link=selenium");
        _selenium.WaitForPageToLoad("30000");
        return new SeleniumTutorials(_selenium);
    }

    /// <summary>
    /// Click on the blog or blog year and then wait for the page to load
    /// </summary>
    /// <param name="year">blog or blog year
    /// <returns>Object representing /blog.* pages</returns>
    public Blog ClickBlogYear(string year)
    {
        _selenium.Click("link=" + year);
        _selenium.WaitForPageToLoad("30000");
        return new Blog(_selenium);
    }
    // Add more methods as you need them
}

public class SeleniumXPathTutorial
{
    private readonly ISelenium _selenium;

    public const string FirstInput = "number1";
    public const string SecondInput = "number2";
    public const string Total = "total";

    public SeleniumXPathTutorial(ISelenium selenium)
    {
        this._selenium = selenium;
    }

    public bool IsInputOnScreen(string locator)
    {
        return _selenium.IsElementPresent(locator);
    }
}

и тогда тестовый класс будет выглядеть

[TestFixture]
public class SiteTests
{
    private ISelenium selenium;
    [SetUp]
    public void Setup()
    {
        selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://www.theautomatedtester.co.uk");
        selenium.Start();
    }

    [TearDown]
    public void Teardown()
    {
        selenium.Stop();
    }

    [Test]
    public void ShouldLoadHomeThenGoToXpathTutorial()
    {
        Home home = new Home(selenium);
        SeleniumTutorials seleniumTutorials = home.ClickSelenium();
        SeleniumXPathTutorial seleniumXPathTutorial = seleniumTutorials.ClickXpathTutorial();
        Assert.True(seleniumXPathTutorial.
                    IsInputOnScreen(SeleniumXPathTutorial.FirstInput));
        Assert.True(seleniumXPathTutorial
                    .IsInputOnScreen(SeleniumXPathTutorial.SecondInput));
        Assert.True(seleniumXPathTutorial
                    .IsInputOnScreen(SeleniumXPathTutorial.Total));
    }
}
person AutomatedTester    schedule 25.08.2010
comment
Спасибо. Я видел паттерн Page Object Model, и мы обязательно его изучим, поскольку он больше соответствует OOD. Тем не менее, мы решили начать с командно-процедурного подхода (почему? слишком долго объяснять здесь...), и столкнулись с проблемой сочетания примитивов и не-примитивов. До сих пор я определил больше причин для разделения примитивов и непримитивов, но нам все еще нужно немного поиграть. - person Sebastian; 25.08.2010
comment
Перешел на ПОМ. Мы боялись этого, потому что ожидали больших изменений в навигации по приложению, но теперь это лучший способ сделать это. С изменениями мы разберемся позже. Спасибо вам. - person Sebastian; 26.08.2010
comment
Идея объектной модели страницы состоит в том, чтобы упростить обновление тестов при изменении навигации. - person AutomatedTester; 27.08.2010