How do I specify test method parameters with TestDriven.NET?
Asked Answered
R

5

12

I'm writing unit tests with NUnit and the TestDriven.NET plugin. I'd like to provide parameters to a test method like this :

[TestFixture]
public class MyTests
{
    [Test]
    public void TestLogin(string userName, string password)
    {
        // ...
    }

    ...
}

As you can see, these parameters are private data, so I don't want to hard-code them or put them in a file. Actually I don't want to write them anywhere, I want to be prompted each time I run the test.

When I try to run this test, I get the following message in the output window :

TestCase 'MyProject.MyTests.TestLogin' not executed: No arguments were provided

So my question is, how do I provide these parameters ? I expected TestDriven.NET to display a prompt so that I can enter the values, but it didn't...

Sorry if my question seems stupid, the answer is probably very simple, but I couldn't find anything useful on Google...


EDIT: I just found a way to do it, but it's a dirty trick...

    [Test, TestCaseSource("PromptCredentials")]
    public void TestLogin(string userName, string password)
    {
        // ...
    }

    static object[] PromptCredentials
    {
        get
        {
            string userName = Interaction.InputBox("Enter user name", "Test parameters", "", -1, -1);
            string password = Interaction.InputBox("Enter password", "Test parameters", "", -1, -1);
            return new object[]
            {
                new object[] { userName, password }
            };
        }
    }

I'm still interested in a better solution...

Rodolforodolph answered 5/9, 2009 at 2:52 Comment(2)
I think if you do this you will have trouble running your tests automatically in a CI (Continuous Itegration) environment.Dispense
You're absolutely right. However, it's a small community project, so CI is not really an issue, at least for now.Rodolforodolph
H
2

Unit Tests should normally not take any parameters. You create the necessary data within the test itself.

  • The expected value
  • You call your method you want to test passing the necessary arguments
  • You compare the result with the expected value and the returned value from your tested method

MS Unit tests don't allow the passing of parameters to tests. Instead you need to create Datadriven Unit tests. Try the link, it may help you.

As I mentioned. I wouldn't declare passing arguments to unit tests itself good practice.


Update: I was young :). Consider Sarfraz's answer instead on how to pass parameters to NUnit tests.

Hoiden answered 10/9, 2009 at 8:2 Comment(6)
Thanks, but again, it doesn't solve my problem... How am I supposed to run a test which requires credentials ? I don't want to put my personal username and password in a code that will be shared with others...Rodolforodolph
In such a case use dummy credentials. What kind of logic is your unit test supposed to cover s.t. you need credential handling etc?Hoiden
Oh, I now read your edited post. Couldn't you just use some dummy credentials. A test-user + pass which has the right to access what you need to achieve? Although I'm not quite sure whether the kind of thing you want to reach is really what should be tested by a unit test. Check this: #1258060Hoiden
The component I'm testing connects to VBulletin forum to retrieve authentication cookies. Maybe I could create a dummy account... or perhaps you're right and this shouldn't even be a unit test ;)Rodolforodolph
Understand...well it's always a bit "discussable" what is and what isn't a unit test. In your case I'd say this isn't really what I would capture with a unit test. What I would do is to provide a Dummy authentication cookie and inject it somehow to fake a call to VBulletin. In this way I would test what my logic does with a correct cookie and what with a wrong one. That's in my eye what should be captured with a unit test.Hoiden
Juri and J.R. Garcia are correct. You want unattended, automated tests - that way you can run them from a build server, etc. The way to do this is to use dependency injection with a dummy (stub) object that handles your authentication. In the actual app, you inject the true authentication scheme (implementing the same interface).Haya
C
22

Use the TestCase attribute.

[TestCase("User1", "")]
[TestCase("", "Pass123")]
[TestCase("xxxxxx", "xxxxxx")]
public void TestLogin(string userName, string password)
{
    // ...
}
Compartment answered 13/9, 2011 at 9:57 Comment(3)
+1. This is far better than the chosen answer by handling dependency injection right in the TestCase() parameters instead of parroting off "no arguments in the method". unfortunately, I don't think MS Unit Test has anything like this, just NunitSporadic
This is the correct and short answer. It doesn't matter if this is a good or bad practice.Gypsophila
Please mark this as the correct answer. This answers the question and for me is not bad practice to use params in general. For passwords i'd be less inclined.Narcosis
D
2

I think you can solve this problem by using the RowTest plugin for NUnit found here http://www.andreas-schlapsi.com/2008/01/29/rowtest-extension-120/

You can create simple Data-Driven Tests where the test data is provided by [Row] attributes. So here is an example of a test that is run over and over again with different parameters:

[TestFixture]
public class RowTestSample
{
 [RowTest]
 [Row( 1000, 10, 100.0000)]
 [Row(-1000, 10, -100.0000)]
 [Row( 1000, 7, 142.85715)]
 [Row( 1000, 0.00001, 100000000)]
 [Row(4195835, 3145729, 1.3338196)]
 public void DivisionTest(double numerator, double denominator, double result)
 {
    Assert.AreEqual(result, numerator / denominator, 0.00001);
 }
} 
Dispense answered 10/9, 2009 at 7:32 Comment(2)
Thanks for your answer. I think this plugin is made obsolete by the TestCaseAttribute new in NUnit 2.5 (nunit.org/index.php?p=testCase&r=2.5). Anyway, it doesn't solve my problem : I don't want to hard-code my credentials. I want a prompt to enter it manually when the test is runRodolforodolph
Ah ok. I misunderstood. Nice to know about TestCaseAttribute though :)Dispense
H
2

Unit Tests should normally not take any parameters. You create the necessary data within the test itself.

  • The expected value
  • You call your method you want to test passing the necessary arguments
  • You compare the result with the expected value and the returned value from your tested method

MS Unit tests don't allow the passing of parameters to tests. Instead you need to create Datadriven Unit tests. Try the link, it may help you.

As I mentioned. I wouldn't declare passing arguments to unit tests itself good practice.


Update: I was young :). Consider Sarfraz's answer instead on how to pass parameters to NUnit tests.

Hoiden answered 10/9, 2009 at 8:2 Comment(6)
Thanks, but again, it doesn't solve my problem... How am I supposed to run a test which requires credentials ? I don't want to put my personal username and password in a code that will be shared with others...Rodolforodolph
In such a case use dummy credentials. What kind of logic is your unit test supposed to cover s.t. you need credential handling etc?Hoiden
Oh, I now read your edited post. Couldn't you just use some dummy credentials. A test-user + pass which has the right to access what you need to achieve? Although I'm not quite sure whether the kind of thing you want to reach is really what should be tested by a unit test. Check this: #1258060Hoiden
The component I'm testing connects to VBulletin forum to retrieve authentication cookies. Maybe I could create a dummy account... or perhaps you're right and this shouldn't even be a unit test ;)Rodolforodolph
Understand...well it's always a bit "discussable" what is and what isn't a unit test. In your case I'd say this isn't really what I would capture with a unit test. What I would do is to provide a Dummy authentication cookie and inject it somehow to fake a call to VBulletin. In this way I would test what my logic does with a correct cookie and what with a wrong one. That's in my eye what should be captured with a unit test.Hoiden
Juri and J.R. Garcia are correct. You want unattended, automated tests - that way you can run them from a build server, etc. The way to do this is to use dependency injection with a dummy (stub) object that handles your authentication. In the actual app, you inject the true authentication scheme (implementing the same interface).Haya
K
0

I agree with the other answers that passing arguments may not be best practise, but neither is hard coding credentials or server addresses that may change at some point.

Inspired by the suggested solution in question, I simply read console input instead of using input boxes. The arguments are saved in a file. When starting a the tests, the file is redirected and to be read from some initialization function that should be called before any test cases run.

nunit tests.dll < test.config

This avoids user interaction and should be runnable by any automation script. Downside is that the password still has to be saved somewhere, but at least it can be saved local on the testers machine and is easy to change.

This was for a project, where excel sheets containing the tests (not unit tests by definition) were used to let others create test cases for a bigger server side project without changing any code. It would have been bad if all test cases had to be forced in a single giant excel sheet. Also there was no CI, just many testing environments on different servers.

Katzen answered 19/2, 2012 at 18:2 Comment(0)
S
0

Create a class and store the details of the required variable in const. Note: If you create variable as static then it won't work in the Nunit framework.

public Class Credential
{
    public const string PUBLIC_USER = "[email protected]";
    public const string PASSWORD= "password123";
}

[Test]
[TestCase(Credential.PUBLIC_USER, Credential.PASSWORD)]
public void VerifyLogin(string username, string password)
 
Standish answered 9/6, 2022 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.