Bij geautomatiseerde checks wil je regelmatig een verwachte waarde controleren tegen een actuele waarde. Vroeg of laat kom je dan in aanraking met wildcards: Je wilt bijvoorbeeld weten of de tekst “Er zijn 42 resultaten gevonden” voorkomt, maar het aantal, hier 42, kan variabel zijn. Van 42 wil je dan een wildcard maken.
De meest gebruikte wildcard language is de regular expression. Binnen het testautomatiseren gebruik ik graag regular expressions:
Maar eigenlijk is de belangrijkste reden:
Wat betekent dit? Je hoeft de check niet programmatisch af te handelen. Laten we kijken hoe we dit programmatisch zouden kunnen afhandelen:
public void CheckCorrectResultAmountMessage(string actualText)
{
// Check the start of the text
Assert.IsTrue(actualText.StartsWith("Er zijn "));
// Check the end of the text
Assert.IsTrue(actualText.EndsWith(" resultaten gevonden"));
// Grab the amount
var amountText = actualText.Replace("Er zijn ", "").Replace(" resultaten gevonden", "");
// Check if the amount is a valid integer
int amount;
Assert.IsTrue(int.TryParse(amountText, out amount), "The amount '{0}' is not a valid integer", amountText);
}
Dat is best wel veel gedoe voor de check van 1 regel tekst en dan zijn er nog genoeg cases die niet afgedekt worden: negatieve waarden worden niet als foutief gezien, wat gebeurt er als je ‘4 2’, ‘4.2’, ‘4e2’ of ‘4,2’ terugkrijgt? (dit vereist interne kennis over de int.TryParse method). En hoe ga je dit uitbreiden naar “Er zijn geen resultaten gevonden” en “Er is 1 resultaat gevonden”?
Het onderliggende probleem is: We proberen twee problemen tegelijkertijd op te lossen: Wat we willen checken en hoe we dat doen. Een betere strategie is om dat uit elkaar te trekken.
We kunnen dit oplossen door een regular expression te gebruiken:
public void CheckCorrectResultAmountMessage(string actualText)
{
var pattern = "^Er zijn <0-9>+ resultaten gevonden$";
Assert.IsTrue(Regex.IsMatch(actualText, pattern));
}
Nu kunnen de definitie (wat) en de implementatie (hoe) scheiden waarbij je het pattern op een andere plek bepaalt (in een config file, een database, Excel bestand of je testscenario) dan waar je het test. Als we dit bijvoorbeeld in een Feature file gebruiken dan bepalen we in de feature file de definitie (Wat we testen):
Scenario: There must be an amount displayed if there are results
Given I search for "ipod"
Then I can see the message "Er (zijn \d+ resultaten|is 1 resultaat) gevonden"
Scenario: A message should be shown when no results are found
Given I search for "sony walkman"
Then I can see the message "Er zijn geen resultaten gevonden"
en in de step definitie de implementatie (Hoe we dat doen):
[Then(@"I can see the message ""(.*)""")]
public void ThenICanSeeTheMessage(string expectedMessagePattern)
{
var msg = MyFancyWebApp.GetMessage();
Assert.IsTrue(Regex.IsMatch(msg, expectedMessagePattern));
}
Regular expressions is maar één gebied dat je helpt om definitie en implementatie te scheiden. Binnen applicatie development en dus ook test automatisering is Separation of Concerns een leidend principe dat je binnen een goede code basis veel terug zal zien komen. Samen met DRY (Don't Repeat Yourself) en KISS (Keep It Simple Stupid) vormt dit de basis code principes waarmee je niet alleen jezelf, maar ook je team enorm helpt.
Bas Dam schreef: 30 maart 2017 om 19:07 Goede vraag Mathijs. Als je SpecFlow gebruikt kan je een extra step aanmaken, eentje met “The message should be ‘something'” en een ander “The message should match ‘something'”. Dit zorgt vaak wel weer voor meer orchestratie in je step definities. Een andere manier die nog wel eens gebruikt wordt, vooral in ruwe check data zoals tabellen, is door een signaal karakter te gebruiken voor een regular expression. In het verleden gebruikte ik nog wel een het uitroepteken (dat komt nog uit de WinRunner tijd) maar tegenwoordig vaak een slash (/) voor en achter een pattern (zoals in bijvoorbeeld Java en JavaScript gebruikelijk is). Om nog even op de eerste methode terug te komen, in combinatie met…
Mathijs schreef: 29 maart 2017 om 19:57 Hoe maak je in je testdata onderscheid tussen een regular expression en een gewone tekst, in gewone tekst komen af en toe tekens voor die mis gaan bij een regex zoals haakjes of een plusteken?