Nunit: ์ฝ˜์†” NUnit 3์˜ ํ…Œ์ŠคํŠธ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ

์— ๋งŒ๋“  2015๋…„ 11์›” 26์ผ  ยท  21์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: nunit/nunit

NUnit 2.6.4์—์„œ ๋‚ด ํ…Œ์ŠคํŠธ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋Š” ํ…Œ์ŠคํŠธ DLL์˜ ํ•ด๋‹น bin/Debug ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ƒ๋Œ€ ๊ฒฝ๋กœ๋กœ ํ…Œ์ŠคํŠธ์—์„œ ์™ธ๋ถ€ ํŒŒ์ผ์„ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์ฝ˜์†” ๋Ÿฌ๋„ˆ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์˜๋„์ ์œผ๋กœ ์„ค๊ณ„๋œ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ(*.xml ํŒŒ์ผ)๋ฅผ ์ฝ˜์†” ๋Ÿฌ๋„ˆ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ์— ๋‚จ๊ฒจ๋‘๊ณ  ํ…Œ์ŠคํŠธ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ bin/Debug ์„ค์ •ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@imakowski ์–ด์…ˆ๋ธ”๋ฆฌ ์„ค์ •์—์„œ ํ˜„์žฌ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์•Œ๋ ค์ง„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •ํ•ด

``` C#
[ํ”ฝ์Šค์ฒ˜ ์„ค์ •]
๊ณต๊ฐœ ํด๋ž˜์Šค MySetUpClass
{
[์›ํƒ€์ž„์…‹์—…]
RunBeforeAnyTests()
{
var ๋””๋ ‰ํ† ๋ฆฌ = ๊ฒฝ๋กœ.GetDirectoryName(typeof(MySetUpClass).Assembly.Location);
Environment.CurrentDirectory = ๋””๋ ‰ํ† ๋ฆฌ;

    // or
    Directory.SetCurrentDirectory(dir);
}

}
```

๋ชจ๋“  21 ๋Œ“๊ธ€

์ด๊ฒƒ์€ https://github.com/nunit/nunit/wiki/Breaking-Changes์— ํ‘œ์‹œ๋œ ๋Œ€๋กœ ์˜๋„์ ์œผ๋กœ ์„ค๊ณ„๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ „ ๋ฒ„์ „์—์„œ NUnit์€ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. TestContext.TestDirectory๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์–ด์…ˆ๋ธ”๋ฆฌ๊ฐ€ ํฌํ•จ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋งŽ์€ ํ…Œ์ŠคํŠธ๋ฅผ ๋ง์นฉ๋‹ˆ๋‹ค! ์™œ ๋ฐ”๊ฟจ์–ด? ํ…Œ์ŠคํŠธ๋œ ์•ฑ์˜ ๋Ÿฐํƒ€์ž„ ์ฝ”๋“œ์— ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ํ…Œ์ŠคํŠธ ์–ด์…ˆ๋ธ”๋ฆฌ์˜ ์œ„์น˜๋ผ๋Š” ์ข…์†์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ถ€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@imakowski ์–ด์…ˆ๋ธ”๋ฆฌ ์„ค์ •์—์„œ ํ˜„์žฌ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์•Œ๋ ค์ง„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •ํ•ด

``` C#
[ํ”ฝ์Šค์ฒ˜ ์„ค์ •]
๊ณต๊ฐœ ํด๋ž˜์Šค MySetUpClass
{
[์›ํƒ€์ž„์…‹์—…]
RunBeforeAnyTests()
{
var ๋””๋ ‰ํ† ๋ฆฌ = ๊ฒฝ๋กœ.GetDirectoryName(typeof(MySetUpClass).Assembly.Location);
Environment.CurrentDirectory = ๋””๋ ‰ํ† ๋ฆฌ;

    // or
    Directory.SetCurrentDirectory(dir);
}

}
```

@imakowski ๋‹น์‹ ์€ ๊ทธ๊ฒƒ์„ ์ œ์–ดํ•  ์ˆ˜ ์—†์ง€๋งŒ ์ฝ”๋“œ/์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์„ค์ •๋˜๋Š” ํ˜„์žฌ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ํ•ญ์ƒ ์œ„์—์„œ ์ œ์‹œํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋กœ bin ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Windows์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•Œ์ง€ ๋ชปํ•˜๋Š” ์‚ฌ์ด์— ํ˜„์žฌ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์—ฌ๋Ÿฌ API ํ˜ธ์ถœ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ๊ท€ํ•˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฑฐ์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์„ ๋ฐฉ๋ฌธํ•œ ํ›„์—๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

@rprouse ์ด ์ฝ”๋“œ๋Š” ์„€๋„ ๋ณต์‚ฌ ๋ชจ๋“œ์— ์žˆ์„ ๋•Œ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
var dir = Path.GetDirectoryName(typeof(MySetUpClass).Assembly.Location);

์ด ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
var dir = Path.GetDirectoryName(new Uri(typeof(MySetUpClass).Assembly.CodeBase).LocalPath);

๋˜๋Š” TestContext.CurrentContext.TestDirectory๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. :-)

์šฐ๋ฆฌ๋Š” ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด ์•ฝ๊ฐ„์˜ ์กฐ์ •๊ณผ ํ•จ๊ป˜ ์ œ์•ˆ๋œ ๋Œ€๋กœ Uri๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋˜๋Š” TestContext.CurrentContext.TestDirectory๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. :-)

CurrentContext์—๋Š” ๋” ์ด์ƒ TestDirectory ์†์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” nunit 3.6.1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ๊ฒฝ์šฐ์—๋Š” resharper์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์ž˜๋ชป๋œ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” WorkDirectory๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.(

TestContext.TestDirectory๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์  ์†์„ฑ์ž…๋‹ˆ๋‹ค. WorkDirectory๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๊นŒ?

๊ธ€์Ž„, Visual Studio ๋ธŒ๋ผ์šฐ์ €๋‚˜ ์ปดํŒŒ์ผ๋Ÿฌ ๋˜๋Š” ํ…”๋ ˆ๋ฆญ ๋””์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ nunit 3.5์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡์ด ์ž˜๋ชป๋˜์—ˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š๋‹ค

๋‚ด๊ฐ€ ํ‹€๋ ธ์–ด.

TestContext.CurrentContext.TestDirectory์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ PORTABLE ๋นŒ๋“œ์—๋Š” ์—†์Šต๋‹ˆ๋‹ค.

#if !PORTABLE
        /// <summary>
        /// Gets the directory containing the current test assembly.
        /// </summary>
        public string TestDirectory
        {
            get
            {
                Assembly assembly = _testExecutionContext?.CurrentTest?.TypeInfo?.Assembly;

                if (assembly != null)
                    return AssemblyHelper.GetDirectoryName(assembly);

#if NETSTANDARD1_6
                // Test is null, we may be loading tests rather than executing.
                // Assume that the NUnit framework is in the same directory as the tests
                return AssemblyHelper.GetDirectoryName(typeof(TestContext).GetTypeInfo().Assembly);
#else
                // Test is null, we may be loading tests rather than executing.
                // Assume that calling assembly is the test assembly.
                return AssemblyHelper.GetDirectoryName(Assembly.GetCallingAssembly());
#endif
            }
        }
#endif

3.6.0์—๋Š” ์žˆ์ง€๋งŒ 3.6.1์—๋Š” ์—†์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ github repo๋ฅผ ๋ณด๊ณ  ์žˆ๋Š”๋ฐ ์œ„์—์„œ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ๋„ฃ์€ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ๋“  PORTABLE ๋นŒ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

์˜ˆ, ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค

๊ธ€์Ž„, ๊ทธ๊ฒƒ์ด ๊ฑฐ๊ธฐ์—์—†๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. PORTABLE ๋นŒ๋“œ์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š์œผ๋ฉฐ ๋‚ด๊ฐ€ ์•„๋Š” ํ•œ ์ง€์›ํ•œ ์ ๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” PORTABLE ๋นŒ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ ์ ์ด ์—†์œผ๋ฉฐ CI ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์‹ญ์‹œ์˜ค.

๊ฐ์‚ฌ ํ•ด์š”

๋””๋ ‰ํ† ๋ฆฌ.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);

@CharliePoole ๊ณผ @rprouse๊ฐ€ ๋งํ•œ ๊ฒƒ์„ ์ข…ํ•ฉ ํ•˜๋ฉด ์‹ค์ œ ์ฝ”๋“œ๋ฅผ

[SetUpFixture]
public class MySetUpClass
{
    [OneTimeSetUp]
    public void RunBeforeAnyTests()
    {
        Environment.CurrentDirectory = TestContext.CurrentContext.TestDirectory;
        // or identically under the hoods
        Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory);
    }
}

์ „์—ญ ์ดˆ๊ธฐํ™”์˜ ๊ฒฝ์šฐ

๋„ค์ž„์ŠคํŽ˜์ด์Šค ์•ˆ์— ์œ„์˜ ๋…ผ๋ฆฌ๋ฅผ ๋ฌถ์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ฆ‰

using NUnit.Framework;
using System;
using System.IO;

[SetUpFixture]
public class GlobalSetup
{
    [OneTimeSetUp]
    public void RunBeforeAnyTests()
    {
        Environment.CurrentDirectory = TestContext.CurrentContext.TestDirectory;
        // or identically under the hoods
        Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory);
    }
}

๋˜ํ•œ TestContext.CurrentContext.TestDirectory ์—๋Š” ์ฝ”๋„ˆ ์ผ€์ด์Šค๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋” ๋งŽ์€ ์ •๋ณด๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ typeof(MySetUpClass).Assembly.Location ๋ณด๋‹ค ์„ ํƒํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ typeof(MySetUpClass).Assembly.Location๋ณด๋‹ค ์„ ํƒํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Location ๋Š” ์–ด์…ˆ๋ธ”๋ฆฌ๊ฐ€ ์„€๋„ ๋ณต์‚ฌ๋œ ๊ฒฝ์šฐ ์„€๋„ ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. CodeBase ๋Œ€์‹  Uri ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ TestDirectory ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. #2872 ์ฐธ์กฐ, catchํ•  ์ˆ˜ ์—†๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. OneTimeSetup ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋Š” ์•Œ ์ˆ˜ ์—†์ง€๋งŒ(๊ทธ๋ ‡์ง€ ์•Š๋‹ค๊ณ  ๊ฐ€์ •ํ•จ) ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰