テストを無視する


ほとんどのテストフレームワークのテストを無効にする機能があります.これは通常、テストランナーに個々のテストメソッドを無視するよう指示する一種の注釈を追加することで行われます.
[TestFixture]
public class SomeTests {

    [Test]
    public void RegularTest() 
    {
        ...
    }

    [Test]
    [Ignore] // Ignore a single test
    public void IgnoredTest() 
    {
        ...
    }
}
また、クラスレベルで注釈を追加することによって、全テストフィクスチャのすべてのテストを無効にすることも可能です.
[TestFixture]
[Ignore] // Ignore all tests
public class IgnoredTests {

    [Test]
    public void IgnoredTest() 
    {
        ...
    }

    [Test]
    public void AnotherIgnoredTest() 
    {
        ...
    }
}
しばらくして、私はテストの実行を防ぐためにこの種の機能を使用しないことを理解するようになりました.私は他の人々の開発ワークフローを観察し始めたとき、私はこれに気づいた.いくつかの開発者にとって、テストを無視することができるのは、テストフレームワークの非常に重要な特徴であるようです.テストを無視する必要性は、テストの最初のアプローチよりもアプローチ後のテストでより一般的です.非常に簡単なコード例を見てみましょう.
public class Task
{
    public Person Assignee { get; private set; }

    public void Assign(Person personToAssign)
    {
        Assignee = personToAssign;
    }
}
我々は我々の顧客にオンラインカンバンボードサービスを提供するアプリケーションを構築したと仮定します.このアプリケーションのドメインでは、クラスのタスクという名前です.現在、タスクを特定の人に割り当てることができます.これは代入メソッドのテストがどのように見えるかです.
[TestFixture]
public class TaskTests
{
    [Test]
    public void It_should_be_able_to_assign_a_person_to_a_task()
    {
        var person = new Person("Joe");

        var SUT = new Task();
        SUT.Assign(person);

        Assert.That(SUT.Assignee, Is.SameAs(person));
    }
}
最近では、1人だけの仕事に割り当てることができることは過去からの遺物です.したがって、すべての“アンサンブル”の光の中で、ビジネスは、単一のタスクに複数の人々を割り当てることが可能かどうかを要求した.
テストの最初のアプローチがどのように見えるか見ましょう.明らかに、我々は失敗テストを書くことから始めます.そこで、次のテストメソッドをtasktest test fixtureに追加します.
[Test]
public void It_should_be_able_to_assign_multiple_people_to_a_task()
{
    var people = new[]
    {
        new Person("Joe"),
        new Person("Annie")
    };

    var SUT = new Task();
    SUT.Assign(people);
}
この新しいコードは、現在のところ、Assignメソッドがコレクションの代わりに単一のPersonオブジェクトだけを受け入れるとき、この時点でコンパイルされません.コンパイルしないテストメソッドが失敗したテストとして修飾されるので、これは良いことです.代入メソッドの新しいオーバーロードを追加することでこれを修正しましょう.
public class Task
{
    public Person Assignee { get; private set; }

    public void Assign(Person personToAssign)
    {
        Assignee = personToAssign;
    }

    public void Assign(IEnumerable<Person> peopleToAssign)
    {

    }
}
当分の間、この新しい方法の実装を空にします.今すぐアプリケーションのコードが再びコンパイルされます.また、テストを実行するときにすべてのテストがパスします.我々は再びソフトウェアを動作している.しかし、私たちが完全に新しいテストメソッドの実装を終えなかったので、それはまだ非常に役に立ちません.アサートステートメントはまだ存在しないので、次のステップとして追加します.
[Test]
public void It_should_be_able_to_assign_multiple_people_to_a_task()
{
    var people = new[]
    {
        new Person("Joe"),
        new Person("Annie")
    };

    var SUT = new Task();
    SUT.Assign(people);

    Assert.That(SUT.Assignees, Is.SameAs(people));
}
assert文を追加することで、コードがもうコンパイルされないことがわかります.コンパイルしないテストメソッドが失敗したテストとして修飾されるので、これは良いことです.これを解決するには、タスククラスにAssigneesプロパティを追加する必要があります.
public class Task
{
    public Person Assignee { get; private set; }
    public IEnumerable<Person> Assignees { get; private set; }

    public void Assign(Person personToAssign)
    {
        Assignee = personToAssign;
    }

    public void Assign(IEnumerable<Person> peopleToAssign)
    {

    }
}
今、我々は再びコードをコンパイルすることができます.しかし、すべてのテストを再度実行すると、我々が追加したassert文がテストに失敗したことがわかります.このテストパスを作成するには、新たにオーバーロードされた代入メソッドに必要な実装を追加する必要があります.
public class Task
{
    public Person Assignee { get; private set; }
    public IEnumerable<Person> Assignees { get; private set; }

    public void Assign(Person personToAssign)
    {
        Assignee = personToAssign;
    }

    public void Assign(IEnumerable<Person> peopleToAssign)
    {
        Assignees = peopleToAssign;
    }
}
テストスイートを再度実行すると、すべてのテストが緑色であることに気付きます.我々は再びソフトウェアを動作している.
コードベースの残りの部分は、単一のPersonオブジェクトを受け入れる代入メソッドを使用します.そこで、次のステップは、Assignメソッドの新しいバージョンを使用するように、Taskクラスのすべてのクライアントコードを移行することです.失敗したテストを書いて、人のオブジェクトのコレクションを受け入れる代入メソッドを使用して渡すことによって、この移行について行きます.元の代入メソッドが完全に置き換えられたとき、我々は対応するテストだけでなく、メソッド自体を削除することができます.
このワークフロー中、既存のものを無視せずにテストをすべて実行することができます.同じ例を使ってテスト最初のアプローチをテスト最後のアプローチと比較しましょう.タスククラスで必要な変更を行うことで、すぐに起動します.
public class Task
{
    public IEnumerable<Person> Assignees { get; private set; }

    public void Assign(IEnumerable<Person> peopleToAssign)
    {
        Assignees = peopleToAssign;
    }
}
私たちはassigneeプロパティをassigneesに変更しましたが、また、その型をIEnumerable <> personに変更しました.同様に
代入メソッドのパラメーターをIEnumerable < Person > PeopleToAssignに変更しました.この変更を行うことによって
方法は、我々はタスククラスの契約を破った.その結果、コードはもうコンパイルされません.
まず、代入メソッドを検証するテストのコードを変更する必要があります.我々は、我々がコードを開発している間、テストがどのように我々を背負っているかについて、我々の同僚に少し不満を言います.我々が文句を言われたあと、我々は線sutをコメントアウトします.代入するそして、テストメソッドのignore属性をスラップします.私たちは、私たちが後でこのテストを修正するつもりであると私たちに言います.
[TestFixture]
public class TaskTests
{
    [Test]
    [Ignore("Meh")]
    public void It_should_be_able_to_assign_a_person_to_a_task()
    {
        var person = new Person("Joe");

        var SUT = new Task();
        //SUT.Assign(person);

        Assert.That(SUT.Assignees, Is.SameAs(person));
    }
}
次に、注意を必要とする生産コードの他の場所があることを発見します.代入メソッドの1つの呼び出し元があるかもしれません、あるいは、このメソッドを呼ぶコードベースでいくつかの場所があるかもしれません.変更したコードを変更する必要があるコードに3つの場所があるとします.いくつかの他のテストを無効にするためにいくつかの追加無視属性を追加した後、すべてが今コンパイルされます.
我々が現在会議に引っかかると仮定してください.会議が終了したとき、我々は、無視されたテストを忘れてしまった.結局のところ、我々は我々の機能に取り組んでいきたい.“Stressed and always in a hurry” .
この努力の後でさえ、我々が我々が働くソフトウェアを持っているかどうかについて手掛かりを持っていないことに注意してください.ここに提示された簡単な例は、重要ではないことに注意してください.現代のIDEのリファクタリング機能を使用して必要な変更を行うことができました.それは要領ではない.ポイントはワークフローの違いです.
テストの実行を無効にする必要があると感じるときはいつでも、より良いアプローチを見つけることを考えたい.テストは我々の方法で立つためにそこにあるべきではない.むしろ彼らは開発プロセスを通して私たちを導くことができます.テスト駆動開発は、最初にテストを書くだけではありません.それは非常に短い繰り返しで働くことができることです.重要な部分は、すべての反復の終わりまでに、我々が働くコードを持っているということです.最初に書くテストは、そのワークフローを通して私たちを案内する手段です.