Разделы портала

Онлайн-тренинги

.
Принципы SOLID для тестировщиков: принцип открытости/закрытости
05.08.2024 00:00

Автор: Кристин Джеквони (Kristin Jackvony)
Оригинал статьи
Перевод: Ольга Алифанова

В этом месяце мы продолжим изучение принципов SOLID, разбираясь с буквой «О» - принципом открытости/закрытости. Этот принцип гласит, что класс должен быть открыт для расширения, но закрыт для изменения.

Что это значит? Это значит, что как только класс использован другим кодом, его нельзя менять. Если вы измените класс, вы можете сломать код, который от него зависит. Вместо этого расширяйте класс, добавляя функциональность.

Разберем на примере. Снова вернемся к классу Login, потому что тестировщики сталкиваются со страницами входа очень часто. Представьте, что в компании несколько различных команд, всем из которых нужно писать UI-автоматизацию для своих фич. Один из инженеров, Джо, создает класс Login, доступный для использования всей компании. Он принимает имя пользователя и пароль в качестве переменных, и использует их для осуществления входа.

class Login {
    constructor(username, password) {
        this.username = username
       this.password = password
    }
    login() {
       driver.findElement(By.id('username'))
           .sendKeys(this.username)
       driver.findElement(By.id('password))
           .sendKeys(this.password)
        driver.findElement(By.id('submit)).click()
    }
}

Всем очевидно, что это полезный класс, и все вызывают его в своих тестах.

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

class Login {
    constructor(username, password, answer) {
        this.username = username
        this.password = password
    }
    login() {
        driver.findElement(By.id('username'))
            .sendKeys(this.username)
        driver.findElement(By.id('password'))
            .sendKeys(this.password)
       driver.findElement(By.id('submit')).click()
    }
    loginWithChallenge() {
        driver.findElement(By.id('username'))
            .sendKeys(this.username)
        driver.findElement(By.id('password'))
            .sendKeys(this.password)
        driver.findElement(By.id('submit')).click()
        driver.findElement(By.id('answer'))
            .sendKeys(this.answer)
        driver.findElement(By.id('submitAnswer')).click()
    }
}

Заметим, что класс Login теперь ожидает третьего параметра – ответа на вопрос. Если Джо внедрит эти изменения, тесты коллег сломаются, потому что они не рассчитывают на эту переменную, создавая копию класса Login. Популярность Джо среди тестировщиков падает.

Вместо этого Джо нужно создать новый класс – LoginWithChallenge, расширяющий класс Login и оставляющий его неизменным.

class LoginWithChallenge extends Login {
    constructor(username, password, answer) {
        super()
        this.username = username
        this.password = password
       this.answer = answer
    }
    loginWithChallenge() {
         this.login(username, password)
         driver.findElement(By.id('answer'))
            .sendKeys(this.answer)
       driver.findElement(By.id('submitAnswer')).click()
    }
}

Теперь тестировщики могут продолжать пользоваться классом Login – в нем ничего не изменилось. Когда они созреют для того, чтобы обновить свои тесты и воспользоваться новой функциональностью, они смогут изменить их, вызывая класс LoginWithChallenge. Класс Login был открыт для расширения, но закрыт для изменения.

Обсудить в форуме