デフォルトでは、nunitテストはアルファベット順に実行されます。誰かが実行順序を設定する方法を知っていますか?このための属性はありますか?
デフォルトでは、nunitテストはアルファベット順に実行されます。誰かが実行順序を設定する方法を知っていますか?このための属性はありますか?
回答:
単体テストはそれぞれ独立して実行でき、スタンドアロンで実行できる必要があります。それらがこの基準を満たしている場合、順序は重要ではありません。
ただし、特定のテストを最初に実行したい場合があります。典型的な例は、一部のテストの実行時間が他のテストよりも長い継続的統合の状況です。データベースを使用するテストの前にモックを使用するテストを実行できるように、category属性を使用します。
つまり、これをクイックテストの開始時に配置します
[Category("QuickTests")]
特定の環境条件に依存するテストがある場合は、TestFixtureSetUpおよびTestFixtureTearDown属性を検討してください。これらの属性を使用すると、テストの前後に実行されるメソッドをマークできます。
私が指摘したいのは、ほとんどのレスポンダーはこれらを単体テストであると想定していましたが、質問ではそれらがそうであるとは明記されていませんでした。
nUnitは、さまざまなテスト状況で使用できる優れたツールです。テストの順序を制御したい理由がわかります。
そのような状況では、テスト名に実行順序を組み込むことに頼らざるを得ませんでした。属性を使用して実行順序を指定できると便利です。
001_first_test
002_second_test
ですか?
NUnit 3.2.0にが追加されましたOrderAttribute
。以下を参照してください:
https://github.com/nunit/docs/wiki/Order-Attribute
例:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
テストが順序に依存しているかどうかに関係なく...私たちの中には、秩序だった方法ですべてを制御したいだけのものもあります。
単体テストは通常、複雑さの順に作成されます。では、なぜそれらも複雑さの順序、または作成された順序で実行してはならないのでしょうか。
個人的には、テストを作成した順に実行するのが好きです。TDDでは、連続する各テストは当然より複雑になり、実行に時間がかかります。単純なテストは失敗の原因を示すより良い指標になるので、最初に失敗する方がいいと思います。
しかし、特にテストが他のテストに依存していないことをテストしたい場合は、それらをランダムな順序で実行することの利点もわかります。「ランナーが停止するまでランダムにテストを実行する」にランナーをテストするオプションを追加してみませんか?
私はかなり複雑なWebサイトでSeleniumを使用してテストを行っており、テストスイート全体が30分以上実行される可能性があります。アプリケーション全体をカバーすることはまだできていません。以前のすべてのフォームがテストごとに正しく入力されていることを確認する必要がある場合、これにより、テスト全体にわずかな時間ではなく、かなりの時間が追加されます。テストの実行にオーバーヘッドが多すぎる場合、人々は必要な頻度でテストを実行しません。
したがって、私はそれらを整理して、以前のテストに依存してテキストボックスなどを完成させました。前提条件が有効でない場合、Assert.Ignore()を使用しますが、それらを順番に実行する必要があります。
私は前の答えが本当に好きです。
属性を使用して注文範囲を設定できるように少し変更しました。
namespace SmiMobile.Web.Selenium.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
public class OrderedTestAttribute : Attribute
{
public int Order { get; set; }
public OrderedTestAttribute(int order)
{
Order = order;
}
}
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt = new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[OrderedTest(0)]
public void Test0()
{
Console.WriteLine("This is test zero");
Assert.That(MyInt.I, Is.EqualTo(0));
}
[OrderedTest(2)]
public void ATest0()
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
[OrderedTest(1)]
public void BTest0()
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
[OrderedTest(3)]
public void AAA()
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
var assembly =Assembly.GetExecutingAssembly();
Dictionary<int, List<MethodInfo>> methods = assembly
.GetTypes()
.SelectMany(x => x.GetMethods())
.Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
.GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
foreach (var order in methods.Keys.OrderBy(x => x))
{
foreach (var methodInfo in methods[order])
{
MethodInfo info = methodInfo;
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
object classInstance = Activator.CreateInstance(info.DeclaringType, null);
info.Invoke(classInstance, null);
}
}).SetName(methodInfo.Name);
}
}
}
}
}
}
OrderedTest
NUnit 3ではサポートされなくなりました
私はこれが比較的古い投稿であることを知っていますが、テスト名をぎこちなくせずにテストを維持する別の方法があります。TestCaseSource属性を使用し、渡すオブジェクトにデリゲート(アクション)を持たせることで、順序を完全に制御できるだけでなく、テストに名前を付けることもできます。
ドキュメントによれば、テストソースから返されたコレクション内のアイテムは常にリストされている順序で実行されるため、これは機能します。
これは私が明日行うプレゼンテーションのデモです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace NUnitTest
{
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt= new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
}).SetName(@"Test One");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
}).SetName(@"Test Two");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
}).SetName(@"Test Three");
}
}
}
}
TestCaseSource
順序付けされたテストを実行する方法としてを使用することは、天才のストロークです。よくやった。このアプローチを以下のアプローチと組み合わせて、使いやすくするためにいくつかの変更を加えました。詳細については、私の回答のリンクを参照してください。ただし、根本的なアイデアは、このすばらしい回答からのものです。
TestCaseSource
静的でなければならず、パターンを使用できません。残念。
TestCaseSource
ありません。ソース(変数またはプロパティ)はNUnit 3の静的オブジェクトでなければなりません。そうでない場合、テストは実行されません。また、静的オブジェクト内に動的オブジェクトを作成することはできません。なぜそれがVで動作しないことがあります3。
NUnitフレームワークを使用して実行される、C#で記述されたSelenium WebDriverエンドツーエンドUIテストケースを使用しています。(ユニットケースそのものではありません)
他のテストは前提条件としていくつかのデータを追加する必要があるため、これらのUIテストは確かに実行順序に依存します。(すべてのテストで手順を実行することは現実的ではありません)
10番目のテストケースを追加した後、NUnitがTest_1 Test_10 Test_2 Test_3 ..の順に実行したいと考えています。
したがって、今のところテストケース名をアルファベット順に並べる必要があると思いますが、実行順序を制御するこの小さな機能をNUnitに追加するとよいでしょう。
通常、ユニットテストは独立している必要がありますが、必要な場合は、次のようにメソッドにアルファベット順に名前を付けることができます。
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
またはあなたがすることができます。
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
、t2_
代わりに、または末尾の文字を見逃しがちな文字を使用してテストを開始すると、はるかに簡単になります
テストの順序付けメカニズムを利用するのには非常に十分な理由があります。私自身のテストのほとんどは、セットアップ/ティアダウンなどの優れた手法を使用しています。その他には、膨大な量のデータセットアップが必要です。これを使用して、さまざまな機能をテストできます。これまで、これらの(Selenium Webdriver)統合テストを処理するために大きなテストを使用してきました。ただし、上記のhttps://github.com/nunit/docs/wiki/Order-Attributeに提案された投稿には多くのメリットがあると思います 。注文が非常に価値がある理由の例を次に示します。
この10分の待機時間は、テストスイートの速度を低下させます。多数のテストで同様のキャッシュ遅延を乗算すると、多くの時間を消費します。テストの順序付けにより、テストスイートの最初でデータのセットアップを「テスト」として実行でき、テストの実行の終わりに向けて実行されるテストはキャッシュに依存します。
この質問は本当に古いですが、検索からこれに到達する可能性のある人のために、user3275462とPvtVandals / Ricoから優れた回答を取り、自分の更新のいくつかと一緒にGitHubリポジトリに追加しました。また、関連するブログ投稿を作成しました。詳細については、追加情報をご覧ください。
これがあなた方すべてに役立つことを願っています。また、Category属性を使用して、統合テストや他のエンドツーエンドテストを実際の単体テストと区別することもよくあります。単体テストには順序依存性があるべきではないと指摘する人もいますが、他のタイプのテストはそうすることが多いので、必要なテストのカテゴリのみを実行し、それらのエンドツーエンドテストを順序付けるための良い方法を提供します。
私はNUnitコミュニティーが何も考え出していないことに驚いたので、私はこのようなものを自分で作成しに行きました。
現在、NUnitでテストを注文できるオープンソースライブラリを開発しています。テストフィクスチャを注文したり、「注文したテスト仕様」を注文したりできます。
ライブラリには次の機能があります。
このライブラリは、実際には、MSTestが.orderedtest
ファイルの順序付けをテストする方法に影響を受けています。以下の例をご覧ください。
[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
protected override void DefineTestOrdering() {
TestFixture<Fixture1>();
OrderedTestSpecification<MyOtherOrderedTestFixture>();
TestFixture<Fixture2>();
TestFixture<Fixture3>();
}
protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}
を使用している[TestCase]
場合、引数TestName
はテストの名前を提供します。
指定しない場合、メソッド名と指定された引数に基づいて名前が生成されます。
以下に示すように、テストの実行順序を制御できます。
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
ここでは、メソッド名の"ExpressionTest"
サフィックスに番号を付けました。
アルファベット順に並べられた任意の名前を使用できます。TestCase属性を参照してください。
テストフレームワークが実行するテストを選択する順序に依存しないでください。テストは分離され、独立している必要があります。彼らは、彼らのためにステージを設定したり、彼らの後に片付けたりする他のいくつかのテストに依存すべきではありません。また、テストの実行順序に関係なく、同じ結果が得られるはずです(SUTの特定のスナップショット)。
少しググってみました。いつものように、一部の人々は(根底にあるテスト可能性/設計の問題を解決する代わりに)卑劣なトリックに訴えてきました
参照:優れたテストの特性
TestCaseSource
キーを使用する場合は、override string ToString
方法、その仕組み:
TestCaseクラスがあると仮定します
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
そして、テストケースのリスト:
private static IEnumerable<TestCase> TestSource()
{
return new List<TestCase>
{
new TestCase()
{
Name = "Test 1",
Input = 2,
Expected = 4
},
new TestCase()
{
Name = "Test 2",
Input = 4,
Expected = 16
},
new TestCase()
{
Name = "Test 3",
Input = 10,
Expected = 100
}
};
}
Testメソッドで使用して、何が起こるかを見てみましょう。
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
これは順番にテストされず、出力は次のようになります。
したがって、次のoverride string ToString
ようにクラスに追加したとします。
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
結果が変わり、次のようなテストの順序と名前が取得されます。
注意: