Best practices for form/registration forms

1,589 views
Skip to first unread message

Konzy

unread,
Feb 27, 2017, 9:53:11 AM2/27/17
to SpecFlow
Hi all,

I'm quite new to Specflow and just getting used to the various options that are available for writing steps.

The scenario I'm looking to practice with is filling out a website form with selenium. I've got the following as a template....

Scenario: Create a new user via the Admissions Portal
   
Given I will navigate to the Admissions Portal login page
   
When I click the Create an Account link
   
Then I will be on the Register page
   
Given I have entered a Title
       
And I have entered a First Name
       
And I have entered a Middle Name
       
And I have entered a Surname
       
And I have entered a Date of Birth
       
And I have entered a Gender
       
And I have entered an Email
       
And I have entered a Mobile
       
And I have entered a Password
       
And I have entered a Confirm Password
       
And I have entered a Password Reminder Question
       
And I have entered a Password Reminder Answer
   
When I click on the 'Register' button
   
Then I will get a popup displaying my account details
       
And I will get an email with my account details
       
And I will navigate to the Admissions Portal login page

As it's a registration form, there are quite a few fields to fill in. I'm wishing to run the test with random but somewhat real looking data, so each 'I have entered' step links to a method on my page object which then runs methods in my framework that return the type of data required - e.g. a random actual firstname from an excel list of firstnames, an email made up from the firstname and surname, a strong password generator etc.

As I'm not wishing to hardcode any values in the features file, data tables don't seem appropriate. I could condense all the 'And' steps into a single 'Given I have entered data in all the registration fields' however it's likely I'm going to run different scenarios on this page that use the individual fields again.

Might there be a more elegant solution that I'm not seeing yet?

Many thanks,

xDazedx

unread,
Feb 27, 2017, 10:45:06 AM2/27/17
to SpecFlow
Based on my experience here are a few suggestion.

Add a background step to go to the default url and pull it from the app config.
I typically add what page the user should be on in the step because when you add a few hundred plus test cases, you need to know the right step to use. 

Background:

Given I go to the application URL


Scenario: Create a new user via the Admissions Portal



   
Given I click the Create an Account link on the Admissions Portal
 
When I fill in the Registration page with user information |title|firstName|middleName|surname|dob|gender|email|mobile|
 
And I create password info on the Registration page |password|confirmPassword|
 
And on the Registration page I create password reminder question and answer |question|answer|
 
And I fill in the Register page with DOB information |
   
Then I click on the 'Register' button on the Registration Page
   
And I will get a popup displaying my account details
       
Then I will get an email with my account details
       
And I will navigate to the Admissions Portal login page


Then create steps so that your field names are added to the step correctly. This will make more sense later.

Background:
Given I go to the application URL


Scenario: Create a new user via the Admissions Portal



   
Given I click the Create an Account link on the Admissions Portal
 
When I fill in the Registration page with user information |Mr|random|random|surname|random|Male|random|random|
 
And I create password info on the Registration page |myPass|myPass|
 
And on the Registration page I create password reminder question and answer |random|random|
   
Then I click on the 'Register' button on the Registration Page
   
And I will get a popup displaying my account details
       
Then I will get an email with my account details
       
And I will navigate to the Admissions Portal login page

      
This does a few things for you. When you type the step in "When I fill in the Registration page" it will display the fields like this. Now you know the field values and how to fill in each one.
When I fill in the Registration page with user information \|{title}\|{firstName}\|{middleName}\|{surname}\|{dob}\|{gender}\|{email}\|{mobile}\|

You can now write a case statement for each field. If it is "random" use random data. If it is "n/a" leave it blank else use the field value. This gives the tester a choice of how they want to use each field and makes your steps reusable. Want to test specific value? You can. Random Data? You can. Field validation for blanks? You can. 

Make sense?


Konzy

unread,
Feb 27, 2017, 12:24:12 PM2/27/17
to SpecFlow
Thanks for this, although I'm not following yet....

How did you get from this...


When I fill in the Registration page with user information |Mr|random|random|surname|random|Male|random|random|

To this...

When I fill in the Registration page with user information \|{title}\|{firstName}\|{middleName}\|{surname}\|{dob}\|{gender}\|{email}\|{mobile}\|

I tried generating the step definitions for both these statements and I'm confused as to how to extract the parameters from the table....

        [When(@"I fill in the Registration page with user information \|Mr\|random\|random\|surname\|random\|Male\|random\|random\|")]
       
public void WhenIFillInTheRegistrationPageWithUserInformationMrRandomRandomSurnameRandomMaleRandomRandom() {
           
ScenarioContext.Current.Pending();
       
}

       
[When(@"I fill in the Registration page with user information \\\|\{title}\\\|\{firstName}\\\|\{middleName}\\\|\{surname}\\\|\{dob}\\\|\{gender}\\\|\{email}\\\|\{mobile}\\\|")]
       
public void WhenIFillInTheRegistrationPageWithUserInformationTitleFirstNameMiddleNameSurnameDobGenderEmailMobile() {
           
ScenarioContext.Current.Pending();
       
}

Many thanks,

xDazedx

unread,
Feb 27, 2017, 3:00:36 PM2/27/17
to SpecFlow
Create the statement first using the field names in the input fields.


When I fill in the Registration page with user information |title|firstName|middleName|surname|dob|gender|email|mobile| so you have your field names listed first.

Generate yours steps next and change the input values to be variables. It will look like \|(.*)\|

Then modify your statement to the input values you really want to use:

When I fill in the Registration page with user information |Mr|random|random|Jones|random|Male|random|random|
This will use random firstname, middlename, dob, email and mobile. The rest will use the user input.


The reason I set the field names initially is because once you change the field values, you have no idea what each field is after changing it. Because you created the steps with the field names though, you can now just type "When I fill in the Registration page with user information" on the feature file and it will then list the drop down display the below showing you the value for each field. 

When I fill in the Registration page with user information \|{title}\|{firstName}\|{middleName}\|{surname}\|{dob}\|{gender}\|{email}\|{mobile}\|

The other option is tables or create long winded statements like:

When I fill in the Registration page with user information user title |title| and firstname |firstName| and middle name |middleName| and surname |surname| and date of birth |dob| and gender |gender| and email address |email| and mobile phone number |mobile|


Oscar Rieken

unread,
Feb 28, 2017, 1:47:42 AM2/28/17
to spec...@googlegroups.com
So a few tips, one try and focus on what your users behavior is
Create a new user via the Admissions Portal, thats it all the rest is noise really

you really shouldn't given, when, then, when, then, when, then this violates a really simple pattern called Arrange Act Assert(http://wiki.c2.com/?ArrangeActAssert)
so lets see if we can clean this up a bit.
Scenario: Create a new user via the Admissions Portal
# this could probably be worded better as well but lets start our scenario knowing exactly where we are not hoping we get there
    
Given I am on the Admissions Portal login page
    
When I Register a valid Account
    
Then I will get a popup displaying my account details
        
And I will get an email with my account details

ok that looks pretty good we can also use this to try registering different types of accounts like: 
# you can throw a non capture group on a/an and capture everything between that and Account to have one reusable step
    When I Register an invalid Account
    When I Register a Blue Account
    When I Register a Admin Account


now lets talk about all the steps that are gone. well they are really just noise and we can push down filling out a from to code and we can create factories to build the types of users we want to use in each test

function UserFactory(userType) {
 // do some stuff return a user object with all the required data to fill out the registration form
 // probably be really easy to invoke a method by its name and have that method just return a dictionary of all the user data
}

//some where in a page class
function RegisterAccount(userData) {
  firstName.sendKeys(userData.firstName)
  lastName.sendKeys(userData.LastName)
....... you get the idea
}

WhenIRegisterAccount(accountType) {
 user = UserFactory(accountType) //this calls our factory and returns the type of user we want
 RegisterAccount(user)
}

now we pushed all the noise and stuff that doesn't really matter down into the code.
our scenario reads well so anyone on the team knows what it does. 
we no longer violate AAA for our test.
no more super complex crazy step defs. 







--
You received this message because you are subscribed to the Google Groups "SpecFlow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to specflow+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Chris Bingham

unread,
Feb 28, 2017, 3:38:58 AM2/28/17
to SpecFlow
You're still thinking in terms of UI testing.

Try to describe the desired behaviour in succinct business terms, not in terms of the UI layer.




On Tue, 28 Feb 2017, 09:14 Konzy, <oconnorm...@gmail.com> wrote:
Thanks for this.

I think I get the concept (?). Is the UserFactory a separate class that stores all the properties for a user from the registration form? If I use properties I guess I could pass the whole object reference into RegisterAccount, or have a dictionary in UserFactory that as you say returns key value pairs. UserFactory and RegisterAccount would then be doing the heavy lifting I guess.

If I needed to go back down into specifics, e.g....

Scenario: Create a new user via the Admissions Portal

    
Given I am on the Admissions Portal
 login page
    
When I Register a new Account
        And I enter an invalid email

    Then
 I will see validation against the email field

Maybe I could have an invalid method in my page class that binds to....

I enter an invalid (.*)

And updates the field accordingly.  

At the moment there is only one type of user, and only likely to be one for the foreseeable future, however I can see how the structure might be better.

Many thanks,

--
You received this message because you are subscribed to the Google Groups "SpecFlow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to specflow+u...@googlegroups.com.

Konzy

unread,
Feb 28, 2017, 8:21:05 AM2/28/17
to SpecFlow

Thanks for the comments so far. Appears I probably have much to learn in terms of feature file design. If anyone can point me to any resources that help with this it would be much appreciated. For the most part this is just practice.

I've changed my steps to a hybrid of the answers I got...

Scenario: Create a new user via the Admissions Portal
   
Given I will navigate to the Admissions Portal login page
   
When I click the Create an Account
link
   
Then I will be on the ontrack: prospect - Register page
   
Given I have entered the following values on the registration page
   
| fieldName                  | value  |
   
| Title                      | random |
   
| Firstname                  | random |
   
| Middlename                 | random |
   
| Surname                    | random |
   
| DOB                        | random |
   
| Gender                     | random |
   
| EmailAddress               | random |
   
| MobileNumber               | 0      |
   
| Password                   | random |
   
| SecurityQuestion           | random |
   
| SecurityAnswer             | random |
   
And I click on the Register button
   
Then I will be on the Login page
       
And I will get a popup confirming my registration details

I'm storing the table as a dynamic instance, then passing that instance into my registration page object method which runs all the selenium code in a single method. I can either enter the values explicitly or use random to generate a valid random value.

I appreciate that including the table is perhaps a little too granular. I'm not too sure how my other tests will shape up at the moment so may end up removing it.

As an aside, is it possible for the features file to be data driven and random if needed? I.e. instead of my code handling the 'random' text and generating a value from that, is it possible to insert random and/or data driven values into the features file directly?

Many thanks, 

George Cover

unread,
Mar 8, 2017, 3:13:54 AM3/8/17
to SpecFlow
http://lmgtfy.com/?q=learn+gherkin

The first four links that crop up in that search are all really good. You want to try and get a deeper understanding of the Gherkin language and Behaviour Driven Development (specifically). The original article from Dan North is a good read to get you started - https://dannorth.net/introducing-bdd/

For reference, we'd probably not even have that much in our "register" scenario:

Scenario: Create user via Admissions Portal
 
Given I am viewing the Admissions Portal
 
When I create an Account
 
Then I ashould be asked to Login
 
And I should see a confirmation of my registration details

The real difficulty with Gherkin is that it's English and there are as many opinions on how to write the stuff as there are people writing it :-) Technically there are no examples (acceptance criteria) to demonstrate the above scenario, but we've tended to favour this approach as we understand the code behind these things generates suitable randomised data to achieve it's goals in order for us to be able to execute the scenario multiple times without side effects of data clashes (we're not bothering to clean up data at the moment).

Above all else, the main point (I think) of writing features and scenarios is engagement. The language should be domain driven, or at least consistent across all stakeholders to avoid confusion.

Hope this helps...
Reply all
Reply to author
Forward
0 new messages