Unit tests logged (or run) multiple times - c#

I have this simple test:
protected readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().ReflectedType);
private static int count = 0;
[Test]
public void TestConfiguredSuccessfully()
{
logger.Debug("in test method" + count++);
}
log4net is set up like this:
[TestFixtureSetUp]
public void SetUp()
{
log4net.Config.BasicConfigurator.Configure();
}
The problem is, that if I run this test in nUnit once, I get the output (as expected):
1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method0
But if I press RUN in nUnit.exe again (or more) I get the following:
1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1
1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1
And so on (if I run it 5 times, I'll get 5 repeating lines). Now, if I run the same test alone from reSharper the output is fine and does not repeat. However, if I run this test along side 2 other tests in the same class, the output is repeated three times.
I am totally confused. What the hell is going on here?

Log4net is being re-initialized on each test run, and appender(s) added each time. I suspect that ReSharper does not exhibit the behaviour as it starts a new process each time (the ReSharper test runner) whereas the NUnit GUI does not.
I have had various flavours of this in the past, but for quite a while now I have used a "SetupFixture" to initialize log4net (amongst other things).
[SetUpFixture]
public class UnitTestSuiteSetupTeardown
{
[SetUp]
public void Setup()
{
log4net.Config.BasicConfigurator.Configure();
}
[TearDown]
public void Teardown()
{
//Teardown stuff...
}
}
Add one of these per test assembly, and ensure the class has no namespace. It will be run once for all of your tests i.e. all tests in the assembly. I personally have one of these at solution level and then add it in as a link to each test project.
Update
The example above follows the question and sets up basic configuration. In my actual SetUpFixture I initialize log4net from a log4net configuration file (which I again store at solution level and then add as a link to all test projects), e.g.
[SetUpFixture]
public class UnitTestSuiteSetupTeardown
{
[SetUp]
public void Setup()
{
LogFactory.Configure();
}
[TearDown]
public void Teardown()
{
//Teardown stuff...
}
}
And a sample LogFactory type class.
public static class LogFactory
{
public const string DefaultConfigFileName = "log4net.config";
static ILog GetLogger(Type callingType)
{
return new Log4NetLogger(LogManager.GetLogger(callingType));
}
public static void Configure()
{
Type type = typeof(LogFactory);
FileInfo assemblyDirectory = AssemblyInfo.GetCodeBaseDirectory(type);
FileInfo configFile = new FileInfo(Path.Combine(assemblyDirectory.FullName,
DefaultConfigFileName));
XmlConfigurator.ConfigureAndWatch(configFile);
log4net.ILog log = LogManager.GetLogger(type);
log.ToString();
}
}

Related

Unable to Run [Test]'s together when using [setup] and [teardown] attributes of Nunit with Selenium

Below is the Test class code:
[TestFixture]
public class Playground
{
public static IWebDriver d { set; get; }
[SetUp]
public void Initialize_Browser()
{
d = new ChromeDriver();
d.Manage().Window.Maximize();
d.Url = "https://the-internet.herokuapp.com/";
}
[TearDown]
public void Quit()
{
d.Quit();
}
[Test]
public void Test1()
{
POM p = new POM();
m.Iwait(15);
m.Print("You are now at " + p.main_header_txt + " page");
}
[Test]
public void Test2()
{
POM p = new POM();
p.Hover_Images();
}
Below is one more class which has custom static methods that contain frequently used code: (For Hovering over an element)
public class m
{
static IWebDriver d= Playground.d;
public static void Hover(IWebElement IW)
{
Actions act = new Actions(d);
act.MoveToElement(IW).Build().Perform();
}
}
Below is another class whose method is called in test class.
public class POM
{
static IWebDriver d= Playground.d;
IWebElement hovers_link => d.FindElement(By.LinkText("Hovers"));
public void Hover_Images()
{
hovers_link.Click();
IList<IWebElement> user_image = d.FindElements(By.XPath("//div[#class='figure']"));
foreach (IWebElement ui in user_image)
{
m.Hover(ui);
Thread.Sleep(1000);
}
}
}
After building the solution and running it, Test 1() passes and Test 2() fails.
But, if I run Test2() individually, its a Pass!
Tests pass if i use just [onetimesetup] and [onetimeteardown] instead of [setup] and [teardown].
In Debug Mode, it shows that exception occurs when Hovers method is under execution.
Debug Mode - Exception
Exception details - 1
Exception details - 2
Am I missing something? Kindly help me out.
Thanks in advance.
You don't show the definition of d, the driver instance. From the usage, I assume it is defined as a member variable of the test class. That means both tests use the same instance of d.
My guess is that you have enabled parallel running of your tests, and that they are stepping on one another's common driver. When you use one time setup instead of setup, only one driver is created. This is OK if it is what you intend for the tests. Depending on what operations you perform with the driver, parallel tests may not impact one another.
Another workaround, of course, would be to flag the tests as non-parallelizable.
I have found out the solution,
I had modified the arguments of Hover() method to
public static void Hover(IWebDriver d,IWebElement IW)
{
Actions act = new Actions(d);
act.MoveToElement(IW).Build().Perform();
}
and deleted driver instance from class m
IWebDriver d=d.Playground

How can I tell that my program is under unit test environment

I have a console application. In release environment, it works perfectly at this time. When in IDE debug environment, I don't want the console window close, so I added this function, and calling it in the very end of my program.
[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
Console.WriteLine(message);
Console.ReadKey();
}
It works well for me, when I debug my program. But with unit testing, it still wait for a key before exiting!
The work-around is only unit-testing release edition of my program, or test other functions. But I do want something can identify current session is under unit testing, and use that flag in this function.
I believe this should answer your question. I took a class from there and adapted it to your situation.
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static UnitTestDetector()
{
string testAssemblyName = "Microsoft.VisualStudio.QualityTools.UnitTestFramework";
UnitTestDetector.IsInUnitTest = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.FullName.StartsWith(testAssemblyName));
}
public static bool IsInUnitTest { get; private set; }
}
Then I added a line to your method which if it is running a test it will not hit the Console.ReadKey();
[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
Console.WriteLine(message);
if(!UnitTestDetector.IsInUnitTest)
Console.ReadKey();
}
Note: This would be considered a hack and would not be considered a best practice.
EDIT:
I also created a sample project on github to demonstrate this code. https://github.com/jeffweiler8770/UnitTest
The simple way if your test runs from a dedicated UnitTest project : use a flag in AppSettings...
I would not investigate around patterns for such a purpose, i would run the test in a dedicated UnitTest project with its own configuration.
If you need to collect data maybe should you simply use traces (they can be customized from your .config file)... ?
Hope this helps...
Rather than looking for whether the program was compiled in debug mode, you can look at whether a debugger is attached:
if (Debugger.IsAttached)
{
Console.WriteLine(message);
Console.ReadKey();
}
Note this will only detect if you start with F5 from Visual Studio, not Ctrl-F5 (i.e. Start with Debugging only)
I used a variation of Jeff's UnitTestDetector. I did not want to check the unit test assembly and wanted to control which unit tests would consider this or not.
So I created a simple class with IsInUnitTest defaulting to false.
Then in the unit test classes where I wanted the conditional code to run I added TestInitializer and TestCleanup where I set the bool accordingly.
Then in my regular code I can use UnitTestDetector.IsInUnitTest
Simple UnitTestDetector class:
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static private bool _isInUnitTest = false;
public static bool IsInUnitTest
{
get { return _isInUnitTest; }
set { _isInUnitTest = value; }
}
}
Unit Test to Test this stuff:
[TestClass]
public class UnitTestDetectorTest_WithoutIsInUnitTest
{
[TestMethod]
public void IsInUnitTest_WithoutUnitTestAttribute_False()
{
bool expected = false;
bool actual = UnitTestDetector.IsInUnitTest;
Assert.AreEqual(expected, actual);
}
}
[TestClass]
public class UnitTestDetectorTest_WithIsInUnitTest
{
[TestInitialize()]
public void Initialize()
{
UnitTestDetector.IsInUnitTest = true;
}
[TestCleanup()]
public void Cleanup()
{
UnitTestDetector.IsInUnitTest = false;
}
[TestMethod]
public void IsInUnitTest_WithUnitTestAttribute_True()
{
bool expected = true;
bool actual = UnitTestDetector.IsInUnitTest;
Assert.AreEqual(expected, actual);
}
}
Condition in Code:
if (UnitTestDetector.IsInUnitTest)
return "Hey I'm in the unit test :)";
I know this is old but I really don't like many of these answers, especially anything that hard codes an assembly name or version.
This works well, as long as the class you are testing is not Sealed. It's pretty simple:
Add this class variable to the class you are testing:
protected Boolean IsInUnitTestMode = false;
We default it to false so in production it will always be false.
Add something like this wrapper to your test class
class ProfileTest : Profiles
{
public ProfileTest() : base()
{
IsInUnitTestMode = true;
}
}
In this example Profiles is the class we are testing, ProfileTest is a wrapper class in the test project's namespace. It will never be deployed. The test class uses this to create an instance of the class to be tested:
ProfileTest profiles = new ProfileTest();
As opposed to this:
private Profiles profiles = new Profiles();
The we can use it something like this:
private string ProfilePath
{
get
{
if (IsInUnitTestMode)
return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, UNITTESTFOLDERNAME)).FullName;
else
return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, PROFILEFOLDERNAME)).FullName;
}
}
As I said, this won't work with sealed classes, nor will it work well with static ones. With that said the number of times I actually choose to test for the unit test condition is quite rare. This works extremely well for me.

NUnit TestFixtureSetUp runs multiple times?

I have a basic Test setup using NUnit 2.6 and Visual NUnit in Visual Studio 2010. My problem is that when I'm running all tests it seems like the FixtureSetup method (which has the TestFixtureSetUpAttribute) is running one time for each of the tests.
I've also tried to put the Init code to the constructor, but it gives the same results.
The tests themselves reports their run time to runtime like 0.003 and 0.032 and so on.
[TestFixture]
public class MODatabaseTests
{
[TestFixtureSetUp]
public static void FixtureSetup()
{
// Perform heavy init (~1.5s)
}
[Test]
public void TestA()
{
...
}
[Test]
public void TestB()
{
...
}
}
If you add this code, you can confirm your suspicion:
private static bool initialized = false;
[TestFixtureSetUp]
public static void FixtureSetup()
{
if (initialized) Assert.Fail("fixture setup called multiple times");
initialized = true;
...
}
The test runner may calling every test individually instead of treating a TestFixture as a suite of tests.
As an aside, I would avoid static in unit tests because if you have any static variables, their state would be carried from each run (though the fixture kind of wants this) and you lose the "unit" part of unit testing.

VS Team Test: Multiple Test Initialize Methods in Test Class

I have unit test project called “MyClassTest” in TeamTest. This project has three TestMethods. Each method needs its own test initialization steps. But when I apply TestInitializeAttribute to three initialization methods, it says the attribute should not be used more than once. Then what should be the attribute to be used to initialize each test method in Visual Studio Team Test?
Reference:
VS Team Test: .Net Unit Testing with Excel as Data Source: Adapter Failed
How to create Startup and Cleanup script for Visual Studio Test Project?
VS 2010 Load Tests Results with custom counters
How to log unit test entry and leave in MSTest
Can a unit test project load the target application's app.config file?
According to MSDN the TestInitializeAttribute:
cannot be used more than once (AllowMultiple = false), and
cannot be inherited to create your own TestInitializeAttribute.
So, my suggestion is to create the Test Initialize Methods without the TestInitialize attribute. Then in the unique TestInitialize method check which is the current executed TestMethod and call the appropriate initialize method:
[TestClass]
public class UnitTest
{
public TestContext TestContext { get; set; }
[TestInitialize]
public void Initialize()
{
switch (TestContext.TestName)
{
case "TestMethod1":
this.IntializeTestMethod1();
break;
case "TestMethod2":
this.IntializeTestMethod2();
break;
default:
break;
}
}
[TestMethod]
public void TestMethod1()
{
}
[TestMethod]
public void TestMethod2()
{
}
public void IntializeTestMethod1()
{
//Initialize Test Method 1
}
public void IntializeTestMethod2()
{
//Initialize Test Method 2
}
}
If you have three test methods, and each method has its own initialization steps, then why are you moving initialization to method which will run before every test? Only benefit I see, is that nice switch block, which adds some lines to your source file. But it gives you drawback - looking on any of these test methods, you can't really tell in which context method will be executed. So, I use initialization method to setup only basic context, which is really used by all tests in fixture.
Just move context creation to arrange part of each method.
If you have several methods, which use common context, then just extract method, which will setup context for them, and call it at the arrange part. You also can split each context setup to several steps and reuse those steps (like it done in Given-When-Then tools like Specflow).
And, of course, creating different fixtures also option.
It's a bit of an old post, but I came up with the following which seems to work OK:
First, define an attribute class:
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class InitialiseWithAttribute : Attribute
{
public string Id { get; private set; }
public InitialiseWithAttribute(string id)
{
Id = id;
}
}
then define an extension method in some convenient utilities class:
public static bool IsInitialisedWith(this string testName, string value)
{
bool result = false;
Type testClassType = new StackFrame(1).GetMethod().DeclaringType;
MethodInfo methodInfo = testClassType.GetMethod(testName);
if (methodInfo != null)
{
InitialiseWithAttribute initialiseWithAttribute =
methodInfo.GetCustomAttribute<InitialiseWithAttribute>(true);
if (initialiseWithAttribute != null)
{
result = initialiseWithAttribute.Id == value;
}
}
return result;
}
Now write your tests, thus:
public TestContext TestContext {get; set;}
[TestInitialize]
public void TestInitialise()
{
if (TestContext.TestName.IsInitalisedWith("DoSomethingSpecial")
{
// ... Do something special
}
else
{
// ... Do something normal
}
}
[TestMethod]
[InitialiseWith("DoSomethingSpecial")]
public void MySpecialTest()
{
// The test
}
If they need three seperate inits; then they should probably be in three separate fixtures each with their own init!
At my job we pass in an argument to TestInitialize method to determine how we want initialization to work.
public partial class CommonActions
{
public void TestInitialize(bool adminTest)
{
try
{
if (adminTest)
{
//do stuff
}
We then have a standard initialization in class definition, which defaults to false.
[TestClass]
public class ProjectTestBase : FrameworkTestBase
{
public CommonActions common { get; set; } = new CommonActions();
[TestInitialize]
public void TestInitialize() => common.TestInitialize(false);
Then in the Test cases themselves you can override the TestInitialize for any test you want.
[TestClass]
public class SetReportsInAdmin : ProjectTestBase
{
[TestInitialize]
public new void TestInitialize() => common.TestInitialize(true);
We use a Boolean to tell if Admin test, which needs to have extra overhead for setup. Take this and apply whatever variables you want in a way the gives you multiple initialization through the use of one method.

Using NUnit -- how can I get currently executing test fixture and name?

I'd like to get the currently executing NUnit test in a helper method I'm using. We're actually using NUnit for integration tests here -- not unit tests. When a test finishes, we'd like to have the test clean up some log files when it's done. Currently, I've hacked around this using the StackFrame class:
class TestHelper
{
string CurrentTestFixture;
string CurrentTest;
public TestHelper()
{
var callingFrame = new StackFrame(1);
var method = callingFrame.GetMethod();
CurrentTest = method.Name;
var type = method.DeclaringType;
CurrentTestFixture = type.Name;
}
public void HelperMethod()
{
var relativePath = Path.Combine(CurrentTestFixture, CurrentTest);
Directory.Delete(Path.Combine(Configurator.LogPath, relativePath));
}
}
[TestFixture]
class Fix
{
[Test]
public void MyTest()
{
var helper = new TestHelper();
//Do other testing stuff
helper.HelperMethod();
}
[Test]
public void MyTest2()
{
var helper = new TestHelper();
//Do some more testing stuff
helper.HelperMethod();
}
}
This works just fine, except there are cases where I'd like to make the TestHelper class part of my fixture, like this:
[TestFixture]
class Fix
{
private TestHelper helper;
[Setup]
public void Setup()
{
helper = new TestHelper();
}
[TearDown]
public void TearDown()
{
helper.HelperMethod();
}
[Test]
public void MyTest()
{
//Do other testing stuff
}
[Test]
public void MyTest2()
{
//Do some more testing stuff
}
}
I can't simply make this class into a global fixture because sometimes a single test will use it more than once, and sometimes a test need not use it at all. Sometimes a test needs to attach specific properties to the TestHelper.... things like that.
As a result, I'd like to be able to somehow get the currently executing test without having to manually repeat the name of the fixture and test in the several thousand test cases I'm looking at.
Is there a way to get such information?
NUnit 2.5.7 has added an "experimental" TestContext class. One of the properties it contains is TestName. I haven't tried it, so I don't know whether the info is available in the TearDown method.
Moving the code you have in the TestHelper constructor to the HelperMethod would do the trick for you?
class TestHelper
{
public void HelperMethod()
{
string CurrentTestFixture;
string CurrentTest;
var callingFrame = new StackFrame(1);
var method = callingFrame.GetMethod();
CurrentTest = method.Name;
var type = method.DeclaringType;
CurrentTestFixture = type.Name;
var relativePath = Path.Combine(CurrentTestFixture, CurrentTest);
Directory.Delete(Path.Combine(Configurator.LogPath, relativePath));
}
}
By the looks is that you can't because the stack frame at the point of setup and teardown does not include the test method.
As for cleaning up log files it looks like you want to have a log file per test method. Perhaps in this case it might be better to either:
Use a random id as part of the log file name which you can clean up in the teardown of the helper class. If however the name of the test method is required to be part of the log file you could do..
You can implement IDisposable todo the cleanup
[Test]
public void MyTest()
{
using(new TestHelper())
{
... test goes here ...
}
}
Or use PostSharp to weave the above code as part of an attribute on your test method.
[Test, TestHelper]
public void MyTest()
{
...
}
[EDIT]
fixed formatting. Added IDisposable

Categories