[Перевод] Применяем BDD правильно

2ec50db802966dd9fca40be060036386.jpg

Три года тому назад я руководил процессом автоматизированного тестирования корпоративного приложения. Для меня, как разработчика, это был захватывающий опыт, и всё это время я думал о том, что этим опытом необходимо поделиться, но то и дело откладывал по разным причинам. Наконец, время пришло. Я надеюсь, что эта статья для кого-то будет полезна. Если да — то я продолжу писать о BDD и автоматизации тестирования. 

Сегодня я хотел бы поговорить об одной распространенной ошибке в автоматизированном тестировании с использованием BDD, а именно — об использовании императивных описаний тестов вместо декларативных. 

Давайте рассмотрим пример в императивном стиле:  

Given uuid variable with the name "account_uuid" 
Given POST request to URL "/create/account"  
""" 
{ 
  "account_uuid": "${account_uuid}" 
  "name": "Test User" 
} 
""" 
When user authenticated with the role "account manager" 
When user go to URL "${base_url}/accounts" 
When get elements by xPath "//label[@id='account0']" and save value into "account_name"
Then variable "account_name" contains the value "Test User"

Предположим, мы использовали Cucumber для привязки определения шага к его имплементации:  

@Given("uuid variable with the name {string}") 
public void uuidVariable(String name) { 
    ... 
} 

@Given("{method} request to URL {string}") 
public void httpRequest(HttpMethod httpMethod, String url, String body) { 
   ... 
} 

@When("user authenticated with the role {string}") 
public void auth(String role) { 
    ... 
} 

@When("user go to URL {string}") 
public void goToUrl(String role) { 
    ... 
} 

@When("get elements by xPath {string} and save value into {string}") 
public void getElementsByXPath(String xPath, String variable) { 
    ... 
} 

@Then ("variable {string} contains the value {string}") 
public void assertEquals(String variableName, String value) { 
    ... 
} 

Почему бы вместо этого не написать простой Java тест? В чем разница?  

@Test 

void accountData(){ 
    //Given 
    var accountUuid = randomUUID(); 
    httpRequest( POST, BASE_URL + "/create/account", Account.builder() 
                     .uuid(accountUuid) 
                     .name("Test User") 
                     .build() 
    );     

    //When 
    auth( "Account manager" ) 
    goToUrl( BASE_URL + "/accounts" ) 

    //Then 
    var accountName = getElementsByXPath( "//label[@id='account0']" );     
    assertEquals( "Test User", accountName ); 
}

Как мы видим, в этом примере мы просто «переводим» Java или любой другой язык программирования на другой синтаксис. Это не дает нам никаких преимуществ. Получившийся результат не выглядит более читаемым (скорее наоборот). Это добавляет еще один дополнительный шаг в разработке — так как нам нужно реализовать привязку кода к определенному шагу в тестах.

Если же мы следуем BDD подходу, мы должны использовать декларативный язык, который должен быть предметно-специфическим! Определения в этом языке должны отвечать на вопрос «Что мы делаем?», а не на вопрос «Как мы это делаем?».  

Давайте взглянем на пример в декларативном стиле:  

Given an account with the name "Test User"
And I am authenticated as an "Account manager"
When I go to the accounts page
Then I am able to see the "Test User" account data

Как видите, в этом примере мы описали только то, что мы ожидаем, без какого-либо объяснения как мы это делаем, а также мы использовали только термины бизнес логики. 

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

BDD обеспечивает связь между всеми этими аспектами: бизнес правилами, имплементацией и тестами. Вы можете найти те же самые слова в любом месте вашей документации, тестах или коде, и понять, а что же здесь происходит. 

Этот подход, конечно, требует много усилий. Стоит ли оно того?  

Решать, конечно, вам. По своему опыту могу сказать, что BDD подход действительно может ускорить процесс тестирования и разработки новой функциональности. Однако я думаю, что нет никакого смысла использовать любой Gherkin-подобный фреймворк, если вы не пишете на нём строго декларативно. Просто используйте обычный язык программирования и сохраните себе время.  

И еще одно — если вы не хотите использовать BDD подход, не имитируйте его.

© Habrahabr.ru