最近それをある程度の形にしようと思って、アレンジしてVisual Studio 2008の単体テスト機能で使えるようにしようとしてVisual Studio 2008の単体テスト機能のカスタマイズを調べてみた。
基本的には自前のassertionでテスト失敗の場合はAssertFailedExceptionをスローすればいいんだけど、そうするとスタックトレースに診断処理や例外をスローする処理のメソッドが含まれてしまう。
これはDebuggerHiddenAttributeやDebuggerNonUserCodeAttributeを使っても避けられない。デバッガとスタックトレースは別。
スタックトレースに含まれないように回避するための属性はないみたいなので、スタックトレースを操作する方向で行こうとすると例外のスタックトレース(Exception.StackTraceプロパティとか)はStackTrace型ではなくて文字列だったりする上にSetterがない。
どうすればいいの?例外のスタックトレースは変更できないの?と思ったけどよく見るとException.StackTraceプロパティはvirtual宣言されているから派生させてオーバーライドすれば、このプロパティで返される値は変更できる。
それでこんなコードでスタックトレースに含められないようにできそう。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MSTestCustomAssertion { public class ExpressionAssert { public static void IsTrue(Expression<Func<bool>> expr) { var result = expr.Compile().Invoke(); if (!result) throw new FailedException("ExpressionAssert.IsTrue failed"); } public class FailedException : AssertFailedException { public FailedException() : base() { } public FailedException(string msg) : base(msg) { } public override string StackTrace { get { var lines = base.StackTrace.Split(new string[] { Environment.NewLine, }, StringSplitOptions.None); var index = Array.FindIndex(lines, x => !x.Contains("ExpressionAssert.")); var st = string.Join(Environment.NewLine, lines, index, lines.Length - index); return st; } } } } }ksksts / junk / source — bitbucket.org
Visual Studioの単体テスト機能でテストを失敗させた場合のスタックトレースにExpressionAssertクラスの処理が含まれない。
Visual Studioに統合された単体テストの機能以外で試してもいないし、例外クラスがAssertFailedExceptionではないという点が気になるけど、とりあえず手軽にするならこの方法でもいいかもしれない。
手間は増えるだろうけどInternalPreserveStackTraceを使ったやり方のほうがちゃんとしていそう。
0 件のコメント:
コメントを投稿