0

I'm using NUnit 2.X library but want to use NUnit 3.X now. I have some problems about migration from 2.X to 3.X. First i have a setup fixture class. Here is the 2.X version;

using System;
using System.IO;
using System.Reflection;
using HalisEnerji.QuantSignal.Logging;
using NUnit.Framework;

namespace HalisEnerji.QuantSignal.Tests
{
    [SetUpFixture]
    public class Initialize
    {
        [SetUp]
        public void SetLogHandler()
        {
            Log.LogHandler = new ConsoleLogHandler();
        }
    }
}

First problem is fixed via change "Setup" attribute with "OneTimeSetUp" attribute. Second problem fixed via add some codes for set test directory. Because i'm using Re-Sharper test engine. Here is final shape of setup fixture;

using System;
using System.IO;
using System.Reflection;
using HalisEnerji.QuantSignal.Logging;
using NUnit.Framework;

namespace HalisEnerji.QuantSignal.Tests
{
    [SetUpFixture]
    public class Initialize
    {
        [OneTimeSetUp]
        public void SetLogHandler()
        {
            Log.LogHandler = new ConsoleLogHandler();

            var assembly = Assembly.GetExecutingAssembly();
            var localPath = new Uri(assembly.CodeBase).LocalPath;
            var direcotyName = Path.GetDirectoryName(localPath);
            if (direcotyName != null)
            {
                Environment.CurrentDirectory = direcotyName;
            }
        }
    }
}

Well after solve setup fixture problem, my real problems begins with use TestCaseSource/TestCaseData. Here is sample 2.X version;

[Theory]
[TestCaseSource("CreateSymbolTestCaseData")]
public void CreateSymbol(string ticker, Symbol expected)
{
    Assert.AreEqual(Symbol.Create(ticker), expected);
}

private TestCaseData[] CreateSymbolTestCaseData()
{
    return new []
    {
        new TestCaseData("SPY", new Symbol(Security.GenerateEquity("SPY"), "SPY")),
        new TestCaseData("EURUSD", new Symbol(Security.GenerateForex("EURUSD"), "EURUSD"))
    };
}

2.X version creating exception and my tests are fail. Shortly exception telling that TestCaseData provider method must be static. Well, after mark method with static identifier test working correctly but this time my other test failing (before use static identifier it's not failing). Why my other test failing? Because it's reading a file from test directory and somehow test working before setup up fixture codes run and change test directory!

Before use static identifier first SetUpFixture codes run and then tests code run. After use static identifier order changing my test that read file from test directory (which is Re-Sharper's temporary directory and not contain necessary file) run first after that SetUpFixture codes run. Any idea how all my tests to be successful?

UPDATE:

Explain some units;

  1. I have Initialize.cs (part of my test assembly) which is responsible setup CurrentDirectory.
  2. I have Config.cs (part of my project infrastructure assembly) which is my project configuration file and it has public static readonly Setttings property which is reading configuration file from CurrentDirectory.
  3. I have ConfigTests.cs (part of my test assembly) which is contain some test methods for read/write Settings property.

When i debug tests;

  1. Before use any static TestCaseSource, they are working below order;

A. Initialize.cs => Setup method

B. Config.cs => static Settings property getter method

C. ConfigTests.cs => first test method

So initialize working first others working later all tests successfully passing from test.

  1. After use static TestCaseSource for inside other test file lets say OrdersTests.cs (excluded from project for first scenario after that included again), somehow working order is changing like below;

A. Config.cs => static Settings property getter method

B. OrdersTests.cs => static TestCaseSource method (not test method)

C. Initialize.cs => Setup method

D. ConfigTests.cs => first test method

E. OrdersTests.cs => first test method

So, my ConfigTests.cs tests failing because Initialize.cs working after Config.cs. I hope with this update my problem is more clear.

Is this problem related NUnit or Resharper or V.Studio? I don't know and all i know is my successfully passing tests are failing now!

UPDATE 2:

Chris,

Yes you are right. I explore project in detail and i saw the problem is related that my project's some classes accessing to static Config class and it's static Settings property (before run test setup fixture method and even before static test case source method!). You talk about order of process of test methods; NUnit doing tests like your said, not like i said. But when i try to use your solution (set current directory before test case source) it's not working. Because of that i solve my problem in another way. I'm not happy but at least my test methods working now. Could you please tell me what are the technical reasons that run static test case methods before initialize/setup method? Is this because of NUnit or because of infrastructure of .Net Framework? I'm not fanatic about NUnit and/or TDD. I don't have deep knowledge about these concepts but it does not make sense to me: run any method before setup method.

Thanks for your interest.

Aytaç Aşan
  • 155
  • 13

1 Answers1

2

Because it's reading a file from test directory and somehow test working before setup up fixture codes run and change test directory!

How are you reading this file? You should use TestContext.CurrentContext.TestDirectory to get the test directory in NUnit 3, rather than relying on the location of the current directory. See the Breaking Changes page for details.

Edit: I also see you've tagged this ReSharper 7.1. You should be aware that this version of resharper does not support NUnit 3 - the first version that did is ReSharper 10. Your tests will appear to run correctly - however you may experience weird side effects, and this may break in any future version of NUnit.


Response to update:

Take a look at NUnit 3's Breaking Changes page. There are two relevant breaking changes between NUnit 2 and 3.

  1. TestCaseSource's must now be static.
  2. The CurrentDirectory is no longer set to Environment.CurrentDirectory by default.

The first you've solved easily enough. The second, is what's now causing you issues.

NUnit 3 runs it's methods in this order:

  1. Evalute TestCaseSource methods (OrdersTests.cs)
  2. Run SetUpFixture (Initialize.cs)
  3. Run Test (ConfigTests/OrdersTests)

I'm not sure what Config.cs is being called before your TestCaseSource method - are you sure of that order? Does anything in CreateSymbolTestCaseData() call anything in Config.cs You could try rewriting your TestCaseSource as such:

private TestCaseData[] CreateSymbolTestCaseData()
{
    Environment.CurrentDirectory = "c:\RequiredDirectory";
    return new []
    {
        new TestCaseData("SPY", new Symbol(Security.GenerateEquity("SPY"), "SPY")),
        new TestCaseData("EURUSD", new Symbol(Security.GenerateForex("EURUSD"), "EURUSD"))
    };
}
Chris
  • 5,882
  • 2
  • 32
  • 57
  • About ReSharper version maybe i'm wrong. I want to clarify it. When i look at version from help menu i see that Ultimate 2017.1.2. Also please don't pay attention to test directory. There 2 ways first via settings and second is alternative way to first. You can check it from here [link](https://stackoverflow.com/questions/16231084/resharper-runs-unittest-from-different-location). – Aytaç Aşan Aug 28 '17 at 00:44
  • You point the breaking changes link. At that link there is "TestCaseSourceAttribute : The attribute forms using a string argument to refer to the data source must now use only static fields, properties or methods". My story start from this point before successfully passing tests not passing anymore! after change my test case source methods to static. – Aytaç Aşan Aug 28 '17 at 00:50
  • Also you can look at this [link](https://github.com/nunit/nunit/issues/1072). At that link there is a sample SetUpFixture class and OneTimeSetUp method. My problem is after start to use NUnit 3.X, i have to change test case source methods to static after that my SetUpFixture's OneTimeSetUp method start to work after some tests. Actually it must be work in first place. Like your said use TestContext.CurrentContext.TestDirectory is inappropriate for my scenario. – Aytaç Aşan Aug 28 '17 at 00:56
  • TestCaseSource's are evaluated before SetUpFixtures are run. You need to either use `TestDirectory`, or set the current directory at the start of your TestCaseSource - if you need it. I'd recommend TestDirectory - rather than relying on the current directory being set in various places across your codebase. – Chris Aug 28 '17 at 20:17
  • I take it `Security.GenerateEquity()` is the method which uses the CurrentDirectory? – Chris Aug 28 '17 at 20:19
  • If you're right about "TestCaseSource's are evaluated before SetUpFixtures are run". So SetUpFixtures name is wrong, it can not be setup! I have almost 4K tests and there is TestData directory which is contain hundreds of test files. And here is your answer; Security.GenerateEquity() not the method that using CurrentDirectory. There are other tests using CurrenDirectory. If you use other guys frameworks this is the result. They decide to use static methods for test case source, they decide not support exception attribute anymore and you have to solve all of these shit! – Aytaç Aşan Aug 29 '17 at 21:04
  • Don't know maybe i'll try to use static directive for SetUpFixture and maybe i have to contact NUnit developers for solve my problem. I don't want to use Resharper's nonsense test directory. I have many test files, how can i use them in that way? – Aytaç Aşan Aug 29 '17 at 21:07
  • You said that "or set the current directory at the start of your TestCaseSource". Are you mean that write SetUp method for each test file which is using CurrentDirectory and set CurrentDirectory like SetUpFixture's OneTimeSetup method? If now could you please write a small sample about it. – Aytaç Aşan Aug 29 '17 at 21:15
  • So sorry but when i try to solve problem myself i see that i can't explain my problem well and do update on my question for clarification. Please look at the question again. – Aytaç Aşan Aug 30 '17 at 02:05
  • @AytacAsan - I've added more to my answer. I hope that helps you to understand the problem better - I think only you can see what your code is doing here, and work out the best way to solve this issue. – Chris Aug 30 '17 at 18:50
  • @AytacAsan - this was a change between NUnit 2 -> 3. I'm not sure why it was required, I'm afraid. – Chris Sep 15 '17 at 14:33