I am using nunit to do some tests for some classes.
There are a couple of operations that are common for all the test classes but require different parameters to work.
So I added the tests in a base class and virtual methods in the base class to provide the parameters.
In the derived test classes I overriden the virtual methods to provide specific parameters for the tests in the base class.
Now my problem is that I want the tests in the base class to be executed only from the derived classes. I am currently using the ignore attribute on the base class to ignore the tests but this causes some warnings when the tests are ran and there is a policy that does not allow me to submit the changes to svn if there are a number of ignored tests.
So how can I run the tests from the base class in the derived classes only without using the ignore attribute on the base class.
You should be able to mark your base class as abstract, this will stop nunit running the tests in that class - meaning you no longer need the ignore attribute.
namespace MyTests
{
[TestFixture]
public abstract class BaseTestClass
{
[Test]
public void CommonTest()
{
}
}
[TestFixture]
public class TestClass1 : BaseTestClass
{
[Test]
public void OtherTest1()
{
}
}
[TestFixture]
public class TestClass2 : BaseTestClass
{
[Test]
public void OtherTest2()
{
}
}
}
Related
I want to group tests like this:
To get this screenshot I used TestCases, but they don't really apply to my needs.
Obviously I don't want this:
[TestCase(TestName = "ShouldDoSomething")]
[TestCase(TestName = "ShouldDoSomethingElse")]
public void OnJoinRoom()
{ ... }
I want something like this:
[TestGroup("OnJoinRoom")]
public void ShouldDoSomething()
{ ... }
[TestGroup("OnJoinRoom")]
public void ShouldDoSomethingElse()
{ ... }
I don't think using subclasses is an option, as the tests are depending on a SetUp method used in the TestFixture class.
In NUnit, TestFixtures are used to group tests as well as to provide a common setup. The normal way to provide a common setup across multiple TestFixtures is to have a common base class like
public class CommonBase
{
[SetUp]
public void CommonSetUp() { }
}
[TestFixture]
public class OnJoinRoom : CommonBase { }
[TestFixture]
public class OnLeaveRoom : CommonBase { }
Notes:
Put all your tests in the derived classes
TestFixture attribute is optional, of course, but do not put it on the base class.
Base class may be abstract if you like.
I'm new to the concept of unit testing and have started using xUnit framework to write my tests. I have a question that I would like to ask about unit testing.
In my test project, I'm going to have an interface which contains all the common test scenarios which will then be implemented by a base class. I didn't want to repeat writing the same code for the same test over and over in each test class files so in the base class I will have the implementation for each of the methods outlined in the interface but marked as virtual as it can be overwritten by the concrete test class when it needs to be.
For example:
public interface IPersonTests
{
void ValidateAge();
void ValidateExperience();
void ValidateAddress();
}
public abstract class BasePersonTests : IPersonTests
{
public virtual void ValidateAge()
{
// method implementation
}
public virtual void ValidateExperience()
{
// method implementation
}
public void ValidateAddress()
{
// method implementation
}
}
public class PersonA : BasePersonTests
{
[Fact]
public override void ValidateAge()
{
// different method implementation to the one specified in the base class
}
}
Is it okay to have a code structure like the above for a unit test project?
I have recently started using XUnit, we have several methods that we need to test that all use the same test methods and same test data. Obviously creating a base class that contains all the test methods and call a virtual method that can be overriden was my first approach.
However when I execute the test runner, the base class is also executed and since the virtual method doesn't contain any code, most of these tests fail.
So how should I structure this code so that the methods in BaseEmployeeTest are not called?
public class BaseEmployeeTest : IEmployeeTest
{
public virtual void CallTestMethod(string userSessionId, long employeeId)
{
// no-op
}
[Theory]
[MemberData(nameof(TestData.Emp), MemberType = typeof(Data))]
public void Pu_CanSee_Own_Customer_Employees(long employeeId)
{
var ex = Record.Exception(() => CallTestMethod(_fixture.PuUserSessionId, employeeId));
Assert.Null(ex);
}
}
public class Test : BaseEmployeeTest
{
public override void CallTestMethod(string userSessionId, long employeeId)
{
CallTestDataMethod("x", "y"
}
}
If you make it abstract, that should cover your need, i.e. replace
public class BaseEmployeeTest
with
public abstract class BaseEmployeeTest
We have a shared basic interface public interface IOperation {...} and lots (tens, soon 100+) different objects that implement IOperation.
We also have tests for all those implementations, all inheriting from base classes called TestOperationCommon that are templated with the actual operations class and types for a Create method to new such an operation. We have implementations for TestOperationCommon with one up to five template parameters (which is enough for all operations).
Now, recently it was decided to make all operation implementations internal and only have IOperation public, which seems like a good idea as those ops are implementation details. And with [InternalsVisibleTo(...)] testing seemed solved, too.
However, now I see that we cannot use our test structure anymore, as the generic parameters to the public test class are now internal (at least the actual class under test is), which leads to
Inconsistent Accessibility .... less accessible than ...
errors. The code below, a public test class cannot inherit from TestOperationCommon with a generic parameter T that is internal. But duplicating all those shared-behavior tests into the specific tests also seems like a bad idea.
Is there a way to get the vstest framework (VS2013+) to test [TestClass]es that are internal?
Or is there another way we can keep the shared tests without having to duplicate lots of code?
Or are we doing it wrong (making those 'implementation detail-classes` internal)?
Code example as request in comment:
public interface IOperation { ... }
internal class SomeOperation : IOperation
{
public SomeOperation(A a, B b, C c) {...}
}
public abstract TestOperationCommon<T, A, B, C>
where T : IOperation
where ...
{
protected abstract T Create(A a, B b, C c);
[TestMethod]
public void TestCommonOperationBehavior()
{
var op = Create(Mock.Of<A>(), Mock.Of<B>(), Mock.Of<C>);
...
}
}
[TestClass]
public class TestSomeOperation : TestOperationCommon<SomeOperation, ...>
{
[TestMethod]
public void TestSpecificSomeOperationStuff() {}
}
Could you creating a test wrapper class?
Something like:
[TestClass]
public class AnnoyingTestSomeOperationWrapper
{
[TestMethod]
public void TestSpecificSomeOperationStuff()
{
new TestSomeOperation().TestSpecificSomeOperationStuff()
}
}
internal class TestSomeOperation : TestOperationCommon<SomeOperation, ...>
{
public void TestSpecificSomeOperationStuff() {}
}
I added these method in a TestBase class :
[ClassInitialize]
public static void InitializBeforeAllTests()
{
}
But when I run in Debug an unit test Test1() :
[TestClass]
public class TestMapping : TestBase
{
[TestMethod]
public void Test1()
{
}
The TestBase.InitializBeforeAllTests() method is never called.
Why?
When declaring ClassInitialize attribute on a method, the method has to be static, public, void and should take a single parameter of type TestContext.
If you're having also other method with the AssemblyInitialize attribute on the same unit test, the test will run but will skip on all test methods and will go directly to AssemblyCleanup or just quit.
Try the example on ClassInitialize attribute in MSDN.
You can setup an assembly initialize method in your base class. Not quite the same as ClassInitialize, but it's a viable option. Source:The Workaround mentioned here.
[TestClass]
public abstract class TestBase
{
[AssemblyInitializeAttribute]
public static void Initialize(TestContext context)
{
// put your initialize code here
}
}
You can also add a Cleanup method:
[AssemblyCleanup]
public static void Cleanup()
{
//clean up stuff here
}
for whatever reason, the unit test framework's UnitTestExecuter only allows one ClassInitialize and one ClassCleanup method to be defined per test class... unlike TestInitialize and TestCleanup methods, which get called in both the derived and base test class...
i know this is a very old question, but its the first to popup in google search when looking for a similar problem, anyhow, here is an update for the answer:
[ClassInitialize(InheritanceBehavior.BeforeEachDerivedClass)]
public static void YOUR_INIT_METHOD_NAME(TestContext context)
Note: you need MSTest.TestFramework-Version 2.0.0 package or newer for this to work.
The MS link is not working anymore.
Anyway, one way to work around this issue is to simply move your initialization code into the constructor of the base class. This will ensure that it gets called from any descendant classes whenever they are instantiated.
[TestClass]
public class TestBase
{
public TestBase()
{
// Initialization Code
}
}
[TestClass]
public class TestMapping : TestBase
{
[TestMethod]
public void Test1()
{
// At this point the base constructor should have been called
}
}
In my case, I had the[Ignore] attribute applied (test is ran manually)
This caused [AssemblyInitialize] to never be called
If I removed the [Ignore] attribute [AssemblyInitialize] was called as expected.
Oddly, [AssemblyCleanup] is still called with or without the [Ignore] applied to my test