2

I am new to C# and am trying to use SpecFlow as I used to use Gherkin by giving a unique name to an item and then passing in the name in the Step Definition. My question is about how to add in the identifier when I create an object so I can call the object without having to pass in the actual name of the object every time that I create a step.

So, for instance the code would look something like this:

    [When(@"I click the (.*) button")]
    public void ClickTheButton(string ButtonName)
    {
         driver.Click(ButtonName)
         //ButtonName would be a string that would call to the ID for the ADD button
    }

I want to be able to put in something like "Add" (so the line would read "When I click the ADD button") and then have the code search for the "ADD" identifier.

I know that this is possible in Ruby/Cucumber by using a DOM and then passing in XML with gherkin names. In Ruby/Cucumber the object would look something like this:

    <button gherkin_name="ADD" key="id" value="add_button_12685"/>

However, I am finding absolutely no way of doing that in C# with SpecFlow and this is something that I really need to be able to do.

Is there a way to do this at all? All I'm really trying to do is link a handle/parameter name that business users could actually use to a Page Object like you can in Ruby/Cucumber without making the user know the code in the background. And, incidentally, the names of the objects are almost exactly like the gherkin line that I added in, thus they are very weird to have a user write. This is the reason that I'd like to have just an identifier for the user.

Thanks in advance for your help.

EDIT: I realise now I was not clear enough in my original post so perhaps some background will help. I am using Selenium-Webdriver to test a website that has hundreds of items on it. Writing a different step for every single item on every single page would be exceedingly tedious and time consuming. Because there are many of the exact same items with the exact same characteristics (for instance there are something like 50 buttons that all behave similarly on a single page and the site is dozens of pages) on the pages, writing a single method for testing them seems the most logical idea. Identifying these items with an identifier that the business could use would cut down on bulk inside of the Steps, the number of steps written, and the likelihood that the business users would feel comfortable using the code which is the end goal.

DAP
  • 51
  • 1
  • 5

2 Answers2

3

You can do what you want if you are using the PageObject pattern and have a property Buttons (probably on a base PageObject class) which exposes the available buttons as a collection (which can be done via reflection) and then you can just do something like:

[When(@"I click the (.*) button")]
public void ClickTheButton(string ButtonName)
{
     myPage.Buttons.First(button=>button.Name==ButtonName).Click;         
}

but I would take what AutomatedChaos said into consideration and not use this in a step in the gerkin but just have this as a helper method something like this

[When(@"I add a widget")]
public void AddAWidget(string ButtonName)
{
     ClickTheButton("Add")        
}

private void ClickTheButton(string ButtonName)
{
     myPage.Buttons.First(button=>button.Name==ButtonName).Click;         
}

your Buttons property doesn't have to be done with reflection, the simplest implementation is something like this:

public IEnumerable<IWebElement> Buttons
{
     yield return AddButton;
     yield return RemoveButton;
     yield return SomeOtherButton;
     //etc etc
}

but using reflection will mean that as you add buttons to the page object you don't need to remember to add them to this method, they will be found automatically.

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
  • Ah, I slowly realized that DAP was not using Web, but WPF. This should be the correct answer. – AutomatedChaos Sep 15 '15 at 09:40
  • Thank you for answering. Does Reflection work on websites? I'm sorry if it seems like a silly question, but I've only been using C# for a couple of days and am unsure what works on what platform. – DAP Sep 15 '15 at 11:27
  • yes reflection still works on websites, but you don't have to use reflection. You could just return each of the buttons. I'll edit my answer – Sam Holder Sep 15 '15 at 11:51
  • How would I then use the IEnumerable elements in the steps? To me it looks like I still have the same problem of not having an identifier linked to an object. I'm sorry in advance if this is a silly question, but my knowledge of C# is fairly limited. – DAP Sep 15 '15 at 12:59
  • you would use it as indicated above in the answer: `myPage.Buttons.First(button=>button.Name==ButtonName).Click` – Sam Holder Sep 15 '15 at 16:11
2

SpecFlow is only the BDD framework. It will not drive browsers itself, you need to install additional packages that drives the browser.

With C#, you have a few options:

  • Selenium, the best known and works with the Page Object you are accustomed with.
  • Fluent Automation, an upcoming library that works as a wrapper on top of Selenium, and makes the interfacing easier (more natural language)
  • CodedUI, Microsofts web and UI test solution that comes natively with Visual Studio Test edition.

On a personal note, I consider Selenium (with or without Fluent Automation) the best fitted to work with SpecFlow (comparisson)

If you want to install Selenium or other packages, you can install the NuGet package manager to easily search, install and update packages for you.

Lastly, have you considered to use more domain specific Gherkin phrases like When I add a Wabberjock instead of When I press the Add button? This is where the power of BDD lies: Exposing the intention while hiding the implementation details.

AutomatedChaos
  • 7,267
  • 2
  • 27
  • 47
  • +l for the last paragraph. – Sam Holder Sep 15 '15 at 08:46
  • I'm sorry I didn't make myself clear originally. I am indeed using Selenium and I am testing a web interface. We do have a page object model which I am attempting to use in conjunction with SpecFlow. I am attempting to add an identifier inside of the objects and there are hundreds of page objects which would mean writing hundreds of steps if I took your last suggestion. Will Reflection still work if it's on a website? – DAP Sep 15 '15 at 10:56