1

Context

I am relatively new to .NET and have decided to use BDD in a project. I'm using Specflow for this.

I have created a feature file using the Gherkin format and generated step definitions.

I'm using Selenium to insert the information from a table in my feature file into the web page and I'm using MSTest to test the results.

My Step Definitions

[Binding]
public class RegisterSteps
{
    private IWebDriver ff = new FirefoxDriver();
    private string username = "";

    [Given(@"you are on the register page")]
    public void GivenYouAreOnTheRegisterPage()
    {         
        ff.Navigate().GoToUrl("http://localhost:55475/Register");
    }

    [Given(@"you enter the following information")]
    public void GivenYouEnterTheFollowingInformation(TechTalk.SpecFlow.Table table)
    {
        username = table.Rows[6]["Value"];
        for (var i = 0; i < table.RowCount; i++)
        {
            var field = table.Rows[i]["Field"];
            var value = table.Rows[i]["Value"];
            field = "mainContentPlaceHolder_TextBox" + field.Replace(" ", string.Empty);
            ff.FindElement(By.Id(field)).SendKeys(value);
        }
    }

    [When(@"you click submit")]
    public void WhenYouClickSubmit()
    {
        ff.FindElement(By.Id("mainContentPlaceHolder_Submit")).Click();
    }

    [Then(@"you should see the message ""(.*)""")]
    public void ThenYouShouldSeeTheMessage(string expectedMessage)
    {
        string message =  ff.FindElement(By.Id("mainContentPlaceHolder_LabelSuccess")).Text;
        Assert.AreEqual(message, expectedMessage);          
    }

    [Then(@"a record should be added to the table")]
    public void ThenARecordShouldBeAddedToTheTable()
    {
        RiskClassesDataContext db = new RiskClassesDataContext();
        var query = from ao in db.ActionOwners
                    where ao.username.Equals(username)
                    select ao;
        Assert.IsNotNull(query.First());
    }
}

Questions

  1. I was hoping to be able to use Linq within my step definitions to check that records are being inserted into various tables. The code above is throwing a NullReferenceException on the constructor of RiskClassesDataContext(). I have been able to create instances of RiskClassesDataContext previously so I'm wondering if this is because I am trying to do this from my Specflow project and not from within my web application.

  2. My last question is just whether or not you think this is the best approach for testing my project. Is selenium with database queries okay to test my entire project or would I better off using say Moq. Or maybe both?

Many Thanks

Naomi Owens
  • 195
  • 2
  • 11
  • What happens when you click the button? A Post? Or a javascript call? – Chris Pitman Mar 09 '13 at 18:23
  • Hi Chris. It's a post that happens. – Naomi Owens Mar 09 '13 at 18:31
  • Here is another question that might handle this: http://stackoverflow.com/questions/9022293/whats-the-alternative-to-use-thread-sleep-when-working-with-selenium-in-system – Chris Pitman Mar 09 '13 at 19:05
  • Using LINQ to whatever provider you are using (I presume Linq2sql or Linq2Entities) is fine, I use LINQ2SQL within my Selenium project heavily. If you've created instances of the data context before, how have you done it? On the first glance, what you've got is fine and should be working. It's perfectly reasonable to do what you are doing *but* it's another added level of complexity that you should remember to go through with new developers or testers to your project, if that is applicable to your situation. – Arran Mar 11 '13 at 11:31

1 Answers1

1

Short answers

  1. I would need to see the code for the RiskClassesDataContext to be sure, but yes, its most likely because your missing something as you connect to the database.
  2. There's nothing wrong with this approach, but if its the Best approach depends on what you want to achieve.

Long answer

In order to decide whether this is the Best way of testing, you would really need to consider which type of testing you are trying to achieve.

  • Are you trying to write some tests that help you write your code?
  • Do you want to come up with a comprehensive library of tests to prove that your code is correct?
  • Should your tests prove that your solution works correctly?

Now at this point you might be saying to yourself that you want all of them, or that they are all the same, but actually there is some subtly different things at play here.

  • If you want some tests just to help write your code, then what is to stop you throwing away those tests after the code is written.
  • If you want to prove your code is correct, then you are thinking of unit testing, probably don't care about talking to databases, and yes Moq would be really useful (other mocking libraries are available).
  • If you want to prove your solution works then we are looking at acceptance testing and you really need to prove the interaction between your code and the database.

The point here is that SpecFlow can be used for all of these things.

If you are trying to do BDD properly, then actually you've been sitting down with your business representative and between the two of you, you've worked out a number of scenarios for the feature that you are thinking of implementing. And of course you've done that before thinking about your code. Just so we don't lock our thinking to any one implementation :-) Now you can sit down and implement your bindings so that they fail.

But what next? Well, of course, at this point we want to write some new code, and since we are good developers we use TDD to help us. And since we are unit testing then we use Mocks to help us isolate each unit of code. This leads our code to evolve so that after writing some of our unit tests, our SpecFlow tests pass too.

This leads us to using our Specification by example tests as an outer process that defines our new feature and unit tests being the inner loop that drives that code towards success. A double red-green-refactor cycle. In addition it means our SpecFlow tests are larger in scope and could include access to that database.

So now if we go back to our questions

  • Are you trying to write some tests that help you write your code?
  • SpecFlow can be a part of it, but I'd advise using TDD as well
  • Do you want to come up with a comprehensive library of tests to prove that your code is correct?
  • Don't bother with SpecFlow, just use nUnit and mocks
  • Should your tests prove that your solution works correctly?
  • This is what SpecFlow excels at, and if it needs a database then go ahead

Try this article for more details.

One final point, if you use a database in your tests, you have to consider how to keep it isolated for multiple test runs. Have a look at using-specflow-for-wpf-in-mvvm for more thoughts on this

Community
  • 1
  • 1
AlSki
  • 6,868
  • 1
  • 26
  • 39