Have you heard about NUnit Attributes and how they’re awesome?

Posted on August 31, 2010. Filed under: NUnit, open source, Selenium, test automation, Tools |

VERY IMPORTANT!!! Some attributes in this article are only available in NUnit 2.5 and later. I would strongly recommend upgrading your NUnit to the newest version.

Okay, so, have you heard about NUnit attributes, and how they’re awesome?
Sure you’ve heard of Setup, Test, TestFixture, and TearDown? But how about Values? How about Range?

The Values attribute allows you to run the same test several times with different values. It makes it where you’re not doing something crazy like copy and pasting the same test, over and over again! I was close to that situation, but it hurt my soul too much to do that. So, in order to save my soul, I had to seek a path for redemption. Here’s what I found:

Okay, to try this, you may need to set up a sample test. If you need to start from scratch, check out my End-to-End Example: http://thetestingblog.com/2009/09/10/selenium-rc-in-c-using-nunit-an-end-to-end-example/

My example test verifies that the text “Daniel Brown” is present on the main testing blog page–a simple pass or fail. But imagine we wanted to run the test 3 times, each time verifying the presence of a different Testing Blog author. Here’s how we would do it using the Values attribute:

        [Test]
        public void ValuesTest([Values("Daniel Brown", "Marisa Seal", "Josh Carroll")] string textPresent)
        {
            selenium.Open("http://www.google.com");
            selenium.Type("q", "thetestingblog.com");
            selenium.Click("btnI");
            selenium.WaitForPageToLoad("60000");
            Assert.IsTrue(selenium.IsTextPresent(textPresent));
        }

As you can see, we’re basically passing the argument “textPresent” into the method. The values are what you want the argument to be. For each value, run the test once with “textPresent” = to that value:
[Values("Daniel Brown", "Marisa Seal", "Josh Carroll")] string stringPresent

So, in the case of this test; here’s how it would run:
SetupTest();
ValuesTest(“Daniel Brown”);
TeardownTest();
SetupTest();
ValuesTest(“Marisa Seal”);
TeardownTest();
SetupTest();
ValuesTest(“Josh Carroll”);
TeardownTest();

This is how it looks in the test runner:

Okay, that wasn’t too bad.  Now, let’s go a crazy.  Let’s get nuts.  Potentially throwing best practices to the wind.  We’re going make this example where it pulls the values from a text file instead of hard coding them.  To do that, let’s add a text file to our project:

Right click on your project (“TestingBlogSeleniumRc”) in the Solution Explorer -> Add -> New Item…

Select Text File and call it ValueList.txt

Open the file in your editor and type the three values into the text file.  One per line:

Daniel Brown
Marisa Seal
Josh Carroll

Next we want to make sure that the text file is copied over into the bin folder on build.

Right click on your project (“TestingBlogSeleniumRc”) in the Solution Explorer and select Properties.  Then select Build Events.  Under the Pre-build event command line: (or post-build; it doesn’t matter) paste in:

copy "$(ProjectDir)ValueList.txt" "$(TargetDir)"

Our test is going to be looking for ValueList.txt so that copy command assures that it’s in the same folder as the test dll.

(FULL CODE EXAMPLE BELOW)

  • We need to add a reference to System.IO
  • Next we’re going to add a global string array to our class called textPresentList
  • We are going to read the ValueList.txt file into an array in our setup.  As coded, it should only be read in the first time the SetupTest() method is run.  If you’re a Unit Test purist, you could easily change it to read the file in every time, but I thought it seemed like a waste.
  • Next we need to add the Range attribute to a copied and renamed version of our first test.  The range should be hard coded from 0 to 2.  (I tried to do something clever like put it from 0 to textPresentList.Length-1, but the compile wouldn’t have it.  These NUnit attribute values, it appears have to be somewhat static.  This kludge that I’m showing is way to get around the static nature if only a little bit.  This way the values can be dynamic even if the number of values can’t be.  By the way, if anyone has a better idea to make it more dynamic, please post it.)
  • Change the selenium.IsTextPresent(textPresent) to selenium.IsTextPresent(textPresentList[i]).
  • Then Compile and Run.

You won’t be able to see the values from the file in the Test Runner, but you could write the value translations to the console so that you could see which index corresponds to which value:
Console.WriteLine("Index " + i +": " + textPresentList[i]);

In the Test Runner, select the Text Output tab to view the output:

The whole point of this post is not to show you what to do, but instead to open up your mind to possibilities.  NUnit has some cool functionality, and most of us never scrape the surface of it’s potential.  I challenge you to go and explore the various attributes available for yourself.  Here’s the link: http://nunit.org/index.php?p=attributes&r=2.5.7

Remember upgrade your NUnit to the newest version.  Chances are that you’re not current.

FULL CODE:

using System;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using NUnit.Framework;
using Selenium;

namespace TestingBlogSeleniumRc
{
	[TestFixture]
	public class FirstTest
	{
		private ISelenium selenium;
        private string[] textPresentList;

		[SetUp]
		public void SetupTest()
		{
            if (textPresentList == null)
                textPresentList = File.ReadAllLines("ValueList.txt");
			selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://www.google.com/");
			selenium.Start();
		}

		[TearDown]
		public void TeardownTest()
		{
		    selenium.Stop();
		}

        [Test]
        public void DynamicValuesTest([Range(0,2)] int i)
		{
			selenium.Open("http://www.google.com");
			selenium.Type("q", "thetestingblog.com");
			selenium.Click("btnI");
			selenium.WaitForPageToLoad("60000");
            Console.WriteLine("Index " + i +": " + textPresentList[i]);
            Assert.IsTrue(selenium.IsTextPresent(textPresentList[i]));
		}
        [Test]
        public void ValuesTest([Values("Daniel Brown", "Marisa Seal", "Josh Carroll")] string textPresent)
        {
            selenium.Open("http://www.google.com");
            selenium.Type("q", "thetestingblog.com");
            selenium.Click("btnI");
            selenium.WaitForPageToLoad("60000");
            Assert.IsTrue(selenium.IsTextPresent(textPresent));
        }
	}
}

Make a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

12 Responses to “Have you heard about NUnit Attributes and how they’re awesome?”

RSS Feed for The Testing Blog Comments RSS Feed

Great post.

It’s a lot easier to copy a file to the output directory by right-clicking the file, selecting “Properties”, and then setting “Copy to Output Directory” to “Copy always” or “Copy if newer”.

To get a real dynamic list of values, use the ValueSource attribute with the name of a method that returns the list of strings you want to use.

Thanks Jason. That whole right copy on Properties thing is so much less convoluted. Which is good! :)

I’ll try to use the ValueSource attribute to see if I can get it to work. I found almost zero examples on how to use it, and I didn’t know how to get it going. If I do, though, I’ll post the results. Thanks again!

Here’s a short example:

[TestFixture]
public class ValueSourceExample
{
[Test]
public void TestValue([ValueSource("GetValues")] string value)
{
Assert.AreEqual(3, value.Length);
}

private IEnumerable GetValues()
{
return new [] { “foo”, “bar”, “baz”, “quux” };
}
}

Sorry, your blog ate the indentation and the pointy brackets. The GetValues method is supposed to return an IEnumerable[T] (where the square brackets are supposed to be pointy brackets).

In your example, Jason, the data source is hard coded. Is it possible to feed a dynamic data source like a dataset or a flat file? When I was trying it before, that’s the problem I ran into. I couldn’t figure out a way to give it a data source that wasn’t set at compile time. That’s why I did the crazy thing with reading in a file. So that it could be more dynamic.

Of course you could get your strings from a file. I just wanted to show you the simplest possible example that demonstrated how the attribute works. Replace the contents of GetValues with “return File.ReadAllLines(…)” and it should work just like your example.

Please tell me how to use both visual studio & nunit simultaneously to run script on selenium rc.also tell functionality of each in running the script….

Great Post. Very useful information.

[...] • Daniel Brown делится примерами работы с атрибутами в NUnit, выбрав Selenium RC в качестве подопытного кролика. [...]

can anyone help me, how to use selinium RC

How to get the target when we are creating the New User and later in the same process how we can test if we dont know the Target of it in the same script….it is possible to run if we create the new script…but need to run in the same script…is it possible???
even i tried the xpath/dom but it it also depends on the alphabetical order so iam unable to get the xact target…kindly pls help me in this.

Regards
boBby

Superb, awesome, fantastic.

I now see a whole new world.


Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...

Follow

Get every new post delivered to your Inbox.