読者です 読者をやめる 読者になる 読者になる

M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

NUnitことはじめ (2)

引きつづき、NUnitについて見ていきます。原文は、“NUnit 2.5.9”です。

今回は型アサーションと例外アサーションについて。かなり意訳や曲解が入っているかも知れません。

******************************

型アサーション(NUnit 2.2.3/2.5)

これらのメソッドは、オブジェクトの型についてアサーションを行うものです。

Assert.IsInstanceOfType( Type expected, object actual );
Assert.IsInstanceOfType( Type expected, object actual, 
                string message );
Assert.IsInstanceOfType( Type expected, object actual, 
                string message, params object[] parms );
				
Assert.IsNotInstanceOfType( Type expected, object actual );
Assert.IsNotInstanceOfType( Type expected, object actual, 
                string message );
Assert.IsNotInstanceOfType( Type expected, object actual, 
                string message, params object[] parms );
			
Assert.IsAssignableFrom( Type expected, object actual );
Assert.IsAssignableFrom( Type expected, object actual, 
                string message );
Assert.IsAssignableFrom( Type expected, object actual, 
                string message, params object[] parms );
				
Assert.IsNotAssignableFrom( Type expected, object actual );
Assert.IsNotAssignableFrom( Type expected, object actual, 
                string message );
Assert.IsNotAssignableFrom( Type expected, object actual, 
                string message, params object[] parms );

NUnit 2.5以降、.NET2.0フレームワーク向けにコンパイルされたNUnitパッケージでは、ジェネリックによる等価比較ができるようになりました。

Assert.IsInstanceOf<T>( object actual );
Assert.IsInstanceOf<T>( object actual, string message );
Assert.IsInstanceOf<T>( object actual, 
                string message, params object[] parms );
				
Assert.IsNotInstanceOf<T>( object actual );
Assert.IsNotInstanceOf<T>( object actual, string message ); 
Assert.IsNotInstanceOf<T>( object actual, 
                string message, params object[] parms );
			
Assert.IsAssignableFrom<T>( object actual );
Assert.IsAssignableFrom<T>( object actual, string message );
Assert.IsAssignableFrom<T>( object actual, 
                string message, params object[] parms );
				
Assert.IsNotAssignableFrom<T>( object actual );
Assert.IsNotAssignableFrom<T>( object actual, string message );
Assert.IsNotAssignableFrom<T>( object actual, 
                string message, params object[] parms );

例外アサーション(NUnit 2.5)

Assert.Throwsは、特殊なメソッドです。値同士を比較するのではなく、デリゲートとして表現されたあるコード断片を実行し、特定の例外が投げられるかどうかを確認します。
このメソッドはまたアサーションが成功したとき、voidではなく例外を返す(訳者:“投げる”〔throws〕ではなく“返す”〔returns〕)点でも、ほかに類がありません。

Assert.Throwsメソッドは、テスト対象の処理が投げるであろう例外に対する制約引数(constraint argument)や、その処理が投げることが期待されている例外の型とともに用いることができます。

Assert.DoesNotThrowメソッドは単純に、そのデリゲートが例外を投げないことを確認するものです。

Assert.CatchメソッドはAssert.Throwsに似ていますが、特定の例外から派生した例外をとる点が異なります。

Exception Assert.Throws( Type expectedExceptionType, TestDelegate code );
Exception Assert.Throws( Type expectedExceptionType, TestDelegate code, 
		string message );
Exception Assert.Throws( Type expectedExceptionType, TestDelegate code, 
		string message, params object[] parms);

Exception Assert.Throws( IResolveConstraint constraint, TestDelegate code );
Exception Assert.Throws( IResolveConstraint constraint, TestDelegate code, 
		string message );
Exception Assert.Throws( IResolveConstraint constraint, TestDelegate code, 
		string message, params object[] parms);

T Assert.Throws<T>( TestDelegate code );
T Assert.Throws<T>( TestDelegate code, string message );
T Assert.Throws<T>( TestDelegate code, string message, 
		params object[] parms);
		
void Assert.DoesNotThrow( TestDelegate code );
void Assert.DoesNotThrow( TestDelegate code, string message );
void Assert.DoesNotThrow( TestDelegate code, string message, 
        params object[] parms);

Exception Assert.Catch( TestDelegate code );
Exception Assert.Catch( TestDelegate code, string message );
Exception Assert.Catch( TestDelegate code, string message, 
        params object[] parms);

Exception Assert.Catch( Type expectedExceptionType, TestDelegate code );
Exception Assert.Catch( Type expectedExceptionType, TestDelegate code, 
		string message );
Exception Assert.Catch( Type expectedExceptionType, TestDelegate code, 
		string message, params object[] parms);

T Assert.Catch<T>( TestDelegate code );
T Assert.Catch<T>( TestDelegate code, string message );
T Assert.Catch<T>( TestDelegate code, string message, 
		params object[] parms);

上記のコードに登場するTestDelegateはvoid TestDelegate()という形式(シグネチャ)のデリゲートです。このデリゲートは問題のコードを実行するために使用されます。.NET2.0のもとでは、これは匿名デリゲートとなるでしょう。C# 3.0としてコンパイルした場合、これはラムダ式となります。

次の例では、同じテストを異なる方法で記述しています。

[TestFixture]
public class AssertThrowsTests
{
  [Test]
  public void Tests()
  {
    // .NET 1.x
    Assert.Throws( typeof(ArgumentException),
      new TestDelegate(MethodThatThrows) );
	  
    // .NET 2.0
    Assert.Throws<ArgumentException>( MethodThatThrows() );

    Assert.Throws<ArgumentException>(
	  delegate { throw new ArgumentException(); } );

    // Using C# 3.0	  
    Assert.Throws<ArgumentException>(
      () => throw new ArgumentException(); } );
  }
  
  void MethodThatThrows()
  {
    throw new ArgumentException();
  }

次の例は、アサーションメソッドにより返される値(例外インスタンス)を使用して、追加の確認を行うものです。

[TestFixture]
public class UsingReturnValue
{
  [Test]
  public void TestException()
  {
    MyException ex = Assert.Throws<MyException>(
      delegate { throw new MyException( "message", 42 ); } );
    Assert.That( ex.Message, Is.EqualTo( "message" ) );
    Assert.That( ex.MyParam, Is.EqualTo( 42 ) ); 
  }

次は、制約オブジェクトを使用するオーバーロードメソッドを使用して、同じことをする例です。

[TestFixture]
public class UsingConstraint
{
  [Test]
  public void TestException()
  {
    Assert.Throws( Is.Typeof<MyException>()
                 .And.Message.EqualTo( "message" )
                 .And.Property( "MyParam" ).EqualTo( 42 ),
      delegate { throw new MyException( "message", 42 ); } );
  }

あなたのコーディングスタイルにあった方の形式を使用してください。

同型アサーションと派生型アサーション

Assert.Throwsを型引数とともに使用した場合、投げられた例外はまさにその型の例外でなくてはなりません。もし何らかの派生型の例外のチェックを行いたい場合、(訳者:制約オブジェクトを使用して)その制約を明記する必要があります。一方、Assert.CatchはAssert.Throwsと異なり、派生型を許容します。次の例を見てください。

// ApplicationExceptionでないといけない。派生型の場合は“失敗”。
Assert.Throws( typeof(ApplicationException), code );
Assert.Throws<ApplicationException>()( code );

// ApplicationExceptionとその派生型のどちらもOK。
Assert.Throws( Is.InstanceOf( typeof(ApplicationException), code );
Assert.Throws( Is.InstanceOf<ApplicationException>(), code );

// ApplicationExceptionとその派生型のどちらもOK。
Assert.Catch<ApplicationException>( code );

//いかなる例外でもOK。
Assert.Catch( code );

こちらも参照してください…

******************************

NUnitことはじめ (3)」に続く──