I have a class which has some unit tests, but when I am running tests I would like the class to be created with a different constructor. Something like this:
[TestFixture]
public class MyClass
{
public MyClass() { /* set up for production */ }
[TestFixtureConstructor]
public MyClass() { /* set up for testing */ }
[Test]
public void FirstTest()
{
// assert some values
}
}
Is this even possible?
I have considered using a static factory method for creating the class in production (with a private constructor), and a public constructor for the testing framework.
Does anyone have any other solutions?
You don't do this.
You do not have your tests written inside the class that you use in real code; you write your tests external to the classes. I believe most testing suites have the concept of 'Teardown' and the opposite; to set up the test environment for a given execution.
To give a quick example of silky's correct approach:
public class MyClass
{
// ...
}
// In a different assembly:
[TestFixture]
public class TestMyClass
{
[SetUp]
public void SetUp()
{
_myClass = new MyClass();
}
[Test]
public void FooReturnsTrue()
{
Assert.That(_myClass.Foo(), Is.True);
}
// more tests
private MyClass _myClass;
}
If you really really want this you can take a look at TestFixtureSetUp.
Here's the introduction:
This attribute is used inside a TestFixture to provide a single set of functions that are performed once prior to executing any of the tests in the fixture. A TestFixture can have only one TestFixtureSetUp method. If more than one is defined the TestFixture will compile successfully but its tests will not run.
Example:
namespace NUnit.Tests
{
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[TestFixtureSetUp] public void Init()
{ /* ... */ }
[TestFixtureTearDown] public void Dispose()
{ /* ... */ }
[Test] public void Add()
{ /* ... */ }
}
}
But you should use this with care, or else it defeats the purpose of unit test.
Related
This is a simple unit Test class with test method called 'TestMethod1()' . when i write ctor inside it, unit test doesn't run anymore. but without ctor test case work as well.
public class OrderTests
{
public OrderTests (int value)
{ }
public void TestMethod1()
{
Xunit.Assert.Equal(7, 7);
}
}
Thanks a lot.
You need to add the Fact attribute to the test so that is recognised as a test and not just a method e.g.:
[Fact]
public void TestMethod1()
{
Xunit.Assert.Equal(7, 7);
}
I have a method
using Microsoft.VisualStudio.TestTools.UnitTesting; // using visual studio's test framework
[TestMethod]
public void ATestMethod()
{
// stuff
}
from a public class ATestClass. This test class runs two types of tests :
tests requiring that a certain software is installed on the machine running the test
tests that can run free
To handle this, I added a public class BaseTestClass from which I made ATestClass derive, and in ATestClass I added a :
public bool isTheSoftwareInstalledOnTheMachine()
{
// stuff
}
and I "decorated" all internal scopes of tests from ATestClass as follows :
[TestMethod]
public void ATestMethod()
{
if (isTheSoftwareInstalledOnTheMachine())
{
// stuff
}
}
I find this horrible. I would rather like to be able to write something like :
[TestMethod]
[RunIfTheSoftwareInstalledOnTheMachine]
public void ATestMethod()
{
// stuff
}
but I don't know if one is allowed to define "custom" [characterizer]'s. (I don't even know the right word for them.) If it is, would that be the best design ? (I heard about the decorator pattern, but I don't know if I could make it generic enough in my context, because I would potentially need to use the condition for many other test classes.) Anyway, how would I proceed with characterizer's ?
I know you're using VS test framework but if you can change to NUnit you can accomplish what you want.
Test case:
using NUnit.Framework;
[TestFixture]
public class MyAppTests
{
[Test]
[RunIfTheSoftwareInstalledOnTheMachine]
public void ATestMethod()
{
// Executes if custom attribute is true, otherwise test case is ignored
}
}
Custom attribute:
using NUnit.Framework;
using NUnit.Framework.Interfaces;
public class TestHelper
{
public static bool IsTheSoftwareInstalledOnTheMachine()
{
// Return state of software
return true;
}
}
public class RunIfTheSoftwareInstalledOnTheMachineAttribute : Attribute, ITestAction
{
public ActionTargets Targets { get; private set; }
public void AfterTest(ITest test) {}
public void BeforeTest(ITest test)
{
if (!TestHelper.IsTheSoftwareInstalledOnTheMachine())
{
Assert.Ignore("Omitting {0}. Software is not installed on machine.", test.Name);
}
}
}
If you define your own attribute you surerly have to check for its existance on your own. You can´t expect your framework to guess what the attribute is for.
But I suppose you don´t even need an attribute to do this. You can simply ignore the test by putting the logic inside the test-method anyway:
[Test]
public void MyTest()
{
if(!RunIfTheSoftwareInstalledOnTheMachine)
Assert.Ignore("Test not run because no software was installed");
// your actual test-code
}
Another approach is to use the CategoryAttribute provided by NUnit, with which you can run only those tests that fall within your provided category:
[Test]
[Category("SoftwareInstalled")]
public void MyTest() { /* ... */ }
EDIT: You could also use the TestCaseAttribute with a specific method that returns a TestCase when the condition is met:
[TestCaseSource("ProvideTestcases")]
public void MyTest() { /* ... */ }
private static IEnumerable<TestCaseData> ProvideTestcases()
{
if(RunIfTheSoftwareInstalledOnTheMachine)
yield return new TestCaseData();
}
If the codition is not met no testcase is generated at all.
If the software being installed on the machine is a requirement for any of the tests to pass and any one test failing means the whole suite fails then why bother checking in multiple tests if the software is installed? Just write a single test to fail if the software is not installed and throw a useful exception. Something like:
[Test]
public void EnsureImportantSoftwareIsInstalled()
{
if(!importantSoftwareIsInstalled)
{
Assert.Fail($"Software X must be installed for the tests in {nameof(MyTestClass)} to run, please install it");
}
}
For Nunit 2.6, a slight variation of the HimBromBeere's answer works well for me. The test case is displayed as ignored.
[TestCaseSource("ProvideTestcases")]
public void MyTest() { /* ... */ }
private static IEnumerable<TestCaseData> ProvideTestcases()
{
if(RunIfTheSoftwareInstalledOnTheMachine)
yield return new TestCaseData().Ignore();
}
I am trying to re-organise some Integration Tests we have so that they use a common class for creating a Database and the Data required in the Database to Test against in other classes in the same assembly using [SetUpFixture] NUnit attribute.
I have :
namespace Tests;
public class TestBaseClass : SolutionBaseClass
{
public void Setup()
{
base.CreateDatabase();
base.CreateData();
}
public void Teardown()
{
base.DestroyDatabase();
}
}
[SetUpFixture]
public class Setup : TestBaseClass
{
[SetUp]
public void Setup()
{
base.Setup();
}
[TearDown]
public void Teardown()
{
base.Teardown();
}
}
then individual test fixture classes:
namespace Tests.Services;
[TestFixture]
public class LibraryTest : TestBaseClass
{
[TestFixtureSetUp]
public void SetupTests()
{
// I know am calling the same Setup twice once from SetUpFixture and TestFixture,
// I have handled it so that only one Database/Data gets set up once (for safety mostly!)
base.SetUp();
// Other class initialisations.
}
}
Any ideas what I am doing wrong, I figure it is a problem with the inheritance model being used, as you can tell I am inheriting this from someone else!!
Thanks.
In NUnit 3 one should use OneTimeSetUpAttribute and OneTimeTearDownAttribute on the static methods of the [SetUpFixture] class. Source: http://bartwullems.blogspot.nl/2015/12/upgrading-to-nunit-30-onetimesetup.html
In NUnit 2.0
[SetUpFixture]
class TestHost
{
[SetUp]
public static void AssemblyInitalize()
{
//Global initialization logic here
}
}
In NUnit 3.0
[SetUpFixture]
class TestHost
{
[OneTimeSetUp]
public static void AssemblyInitalize()
{
//Global initialization logic here
}
}
In NUnit 3.0 TestFixtureSetUp and TestFixtureTearDown has been renamed to OneTimeSetUp and OneTimeTearDown.
Here is the documentation link for above changes:
SetUp and TearDown Changes
Assuming I had a very good reason to want to do the tests below, how could I setup approval tests to name the .approved files UnitTest1.Test1.approved instead of BaseTest.Test1.approved? Thanks
public abstract class BaseTest
{
[TestMethod]
public void Test1()
{
Approvals.Verify(1);
}
[TestMethod]
public void Test2()
{
Approvals.Verify(2);
}
}
[TestClass]
public class UnitTest1 : BaseTest
{
public UnitTest1()
{
// some initialization
}
}
[TestClass]
public class UnitTest2 : BaseTest
{
public UnitTest2()
{
// some initialization
}
}
=== UPDATE ===
Based on Llewellyn's suggestion I added the following code to the ctor of the base class:
public BaseTest()
{
NamerFactory.AdditionalInformation = GetType().Name;
}
Works as expected, I get separate .approved files for each test.
That is an interesting assumption. I am assuming you would want both UnitTest1.Test1.approved & UnitTest2.Test1.approved
The short answer is not exactly, but there are a few work arounds.
WorkAround #1 - NamerFactory (BaseTest.Test1.UnitTest1.approved.txt)
You could rewrite the test to be
[TestMethod]
public void Test2()
{
NamerFactory.AdditionalInformation = this.GetType().Name;
Approvals.Verify(2);
}
btw: this is better with the using statement if you are using the nightly builds from myget https://www.myget.org/gallery/approvaltests
using (NamerFactory.AsEnvironmentSpecificTest(() => this.GetType().Name))
{
Approvals.Verify(1);
}
WorkAround #2 - Call from OutsideClass (UnitTest1.Test1.approved.txt)
You can extract the bulk of the method and then Call it from outside test. There is a good chance you might want all the functionality of a method, but still want the test to be in the extending class. The Approvals call does not need to be in the topmost test method. For example:
public abstract class BaseTest
{
public void Verify1()
{
// other code to do stuff
Approvals.Verify(1);
}
}
[TestClass]
public class UnitTest1 : BaseTest
{
public UnitTest1()
{
// some initialization
}
[TestMethod]
public void Test1()
{
Verify1();
}
}
I'm in the process of setting up tests in NUnit and have a newbie question.
Is it possible to have a Test/s that could be used in multiple [TestFixture]s?
So
[Test]ValidateString(string bob)
Could be called in a series of different [TestFixture]?
That doesn't sound like a test to me. Tests are typically parameterless (unless you're using [TestCase]s) and running it within a context of a single fixture would typically be enough -- it either passes once and that's good or it doesn't and it's a broken test.
If you just have a method that does some validation on a string, you could set it up as a static method on some class (e.g. TestHelpers) and call it from whatever tests (in multiple test fixtures) need it.
Here's another idea: inheritance. You can have a base fixture that has all your tests, and then fixtures that inherit from it that set up whatever variables you need. The tests will run for each fixture. I'm not familiar with Selenium RC, but you should be able to adapt the code below to set up whatever variables you need in various fixtures.
[TestFixture]
public class BaseFixtureTests
{
protected IMyClass _myClass;
[TestFixtureSetUp]
public void FixtureSetup()
{
_myClass = ConfigureMyClass();
}
protected virtual IMyClass ConfigureMyClass()
{
// fixtures that inherit from this will set up _myClass here as they see fit.
}
[Test]
public void MyClassTest1()
{
// test something about _myClass;
}
}
[TestFixture]
public class MySpecificFixture1 : BaseFixtureTests
{
protected override IMyClass ConfigureMyClass()
{
return new MySpecificMyClassImplementation();
}
}
public class MySpecificMyClassImplementation : IMyClass
{
//some implementation
}
You can also add extra tests in each fixture as well that don't test common functionality and don't need to be reused across fixtures.
The newer version of NUnit supports generics. This is a great fit if what you are testing doesn’t need to be configured (only created) from your test code. Here is an example copied from http://nunit.net/blogs/:
[TestFixture(typeof(ArrayList))]
[TestFixture(typeof(List<int>))]
public class IList_Tests<TList> where TList : IList, new()
{
private IList list;
[SetUp]
public void CreateList()
{
this.list = new TList();
}
[Test]
public void CanAddToList()
{
list.Add(1); list.Add(2); list.Add(3);
Assert.AreEqual(3, list.Count);
}
}
I’ve also used Anna’s approach of inheritance. One possible refinement to her example (depending on personal preference): Don’t mark the base class as a TestFixture, only the child classes. Each class that you mark as a TestFixture will be displayed as a set of tests in the NUnit client. You will probably never want to run the base class methods directly because the child is providing all of the setup code. If you remove TestFixture from the base class, running invalid tests won’t be an option in the UI. This allows you to run all the tests and see all green… always a nice feeling.
You might be able to achieve what you want with inheritance.
using NUnit.Framework;
namespace ClassLibrary1
{
[TestFixture]
public class TestFixtureBase
{
[SetUp]
public virtual void Setup()
{
// setup code here
}
[Test]
public void CommonTest1()
{
Assert.True(true);
}
[Test]
public void CommonTest2()
{
Assert.False(false);
}
}
public class MyClassTests : TestFixtureBase
{
[SetUp]
public override void Setup()
{
base.Setup();
// additional setup code
}
[Test]
public void MyClassTest1()
{
Assert.True(true);
}
}
}
You can write a method to be called from multiple [Test] methods. But I don't think there is a way to have the same [Test] included in multiple [TestFixture]s.
[TestFixture]
public class TestsOne{
[Test] public void TryOne(){
Helpers.ValidateString("Work?");
}
}
[TestFixture]
public class TestsTwo{
[Test] public void TryTwo(){
Helpers.ValidateString("Work?");
}
}
public static class Helpers{
public static void ValidateString(string s){
Assert.IsNotNull(s);
}
}