BDD Specflow - Scenario Outline where text spans multiple lines

2.8k views Asked by At

I'm quote new to both BDD and C#, and I've had some success with basic features and step defs.

I'm now trying to write a step def where it asserts some text on a webpage. The problem is, the text spans multiple lines when its displayed, and its HTML is marked up like so:

<span>
    Your username or password didn't match. Please check you've entered them correctly. 
    <br>
    <br>
    If you're not sure about your username (or not sure if you're registered), you can <a href="/MyAccount/ForgottenYourDetails/ForgottenUsername">check your username here</a>. You can then reset your password if you need to.
</span>

and my feature file look like this:

Scenario Outline: Customer tries to login multiple times and on the 5th try locks their account
Given a registered user with a username of 'username' 
    * has <x> failed login attempts
    * is '<status>'
    * I am on the login page
When I enter 'username' and 'password'
    * I click Login
Then I will see the login '<error message>'
Examples: 
    | x | status   | error message|
    | 0 | Unlocked | Your username or password didn't match. Please check you've entered them correctly. If you're not sure about your username (or not sure if you're registered), you can check your username here. You can then reset your password if you need to.                         |
    | 1 | Unlocked | Your username or password didn't match. Please check you've entered them correctly. If you're not sure about your username (or not sure if you're registered), you can check your username here. You can then reset your password if you need to.                         |
    | 2 | Unlocked | Your username or password didn't match. Please check you've entered them correctly. If you're not sure about your username (or not sure if you're registered), you can check your username here. You can then reset your password if you need to.                         |
    | 3 | Unlocked | Your username or password didn't match. Please check you've entered them correctly. If you're not sure about your username (or not sure if you're registered), you can check your username here. You can then reset your password if you need to.                         |
    | 4 | Unlocked | Your account is locked. Don't worry, this is simply a security measure to protect your personal information and ensure only you have access to your account. You can unlock your account yourself online by answering your security question and resetting your password. |

The step I'm having issue with is the THEN step

Then I will see the login '<error message>'

The step definition behind this step is as follows

 [Then(@"I will see the login '(.*)'")]
 public void ThenIWillSeeTheLogin(string p0)
 {
    var actual = WebBrowser.Current.FindElement(By.Id("validationSummarycontainer")).Text;
    Assert.AreEqual(p0, actual);
 }

Because the text I want to check is displayed with line breaks, I've tried a couple of options:

  1. As above, but when asserting the text from the webpage has \r\n\r\n in in place of the line-break, but not in my expected - so fails
  2. I've tried putting \r\n\r\n between "correctly." and "If", eg "correctly.\r\n\r\nIf", however this throws an exception

NUnit.Framework.InconclusiveException was unhandled by user code HResult=-2146233088 Message=No matching step definition found for one or more steps. using System; using TechTalk.SpecFlow;

namespace MyNamespace
{
    [Binding]
    public class StepDefinitions
    {
        [Then(@"I will see the login '(.*)'t match\. Please check you've entered them correctly\.\\r\n\\r\nIf you'(.*)'re registered\), you can check your username here\. You can then reset your password if you need to\.'")]
    public void ThenIWillSeeTheLoginTMatch_PleaseCheckYouVeEnteredThemCorrectly_R_R_IfYouReRegisteredYouCanCheckYourUsernameHere_YouCanThenResetYourPasswordIfYouNeedTo_(string p0, string p1)
        {
            ScenarioContext.Current.Pending();
        }
    }
}

Source=nunit.framework StackTrace: at NUnit.Framework.Assert.Inconclusive(String message, Object[] args) at lambda_method(Closure , String , Object[] ) at TechTalk.SpecFlow.UnitTestProvider.NUnitRuntimeProvider.TestInconclusive(String message) at TechTalk.SpecFlow.UnitTestProvider.NUnitRuntimeProvider.TestPending(String message) at TechTalk.SpecFlow.ErrorHandling.ErrorProvider.ThrowPendingError(TestStatus testStatus, String message) at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.OnAfterLastStep() at TechTalk.SpecFlow.TestRunner.CollectScenarioErrors() at MyBDD.OR_RegressionFeature.ScenarioCleanup() in d:\Data\jonec34\My Documents\Visual Studio 2012\Projects\MyBDD\MyBDD\OR-Regression.feature.cs:line 0 at MyBDD.OR_RegressionFeature.CustomerTriesToLoginMultipleTimesAndOnThe5ThTryLocksTheirAccount(String x, String status, String errorMessage, String[] exampleTags) in d:\Data\jonec34\My Documents\Visual Studio 2012\Projects\MyBDD\MyBDD\OR-Regression.feature:line 38 InnerException:

I'm now stumped unfortunately, if somebody could help or provide other suggestions that'd be fantastic

Thanks in advance

1

There are 1 answers

1
Sam Holder On

If this was me I'd structure my HTML and my test slightly differently. For the test I'd split the message into two parts, the main message and the resolution advice like this:

Scenario Outline: Customer tries to login multiple times and on the 5th try locks their account
Given a registered user with a username of 'username' 
    * has <x> failed login attempts
    * is '<status>'
    * I am on the login page
When I enter 'username' and 'password'
    * I click Login
Then I will see the message '<main error message>'
And I will see the advice '<resolution advice>'
Examples: 
    | x | status   | main error message| resolution advice|
    | 0 | Unlocked | Your username or password didn't match. Please check you've entered them correctly. |If you're not sure about your username (or not sure if you're registered), you can check your username here. You can then reset your password if you need to.                         |

This will allow you to test for both strings in the message separately, just by doing a contains on the element.

In addition to this I would change the html so each piece of text is in its own container (a span or div or paragraph or whatever) so each could be found separately and you could then match up the contents directly and get rid of the <br>'s