2012-03-12 100 views
17

如何從單元測試中獲取單元測試名稱?如何從單元測試中得到運行時的單元測試方法名稱?

我有一個BaseTestFixture類內的以下方法:

public string GetCallerMethodName() 
{ 
    var stackTrace = new StackTrace(); 
    StackFrame stackFrame = stackTrace.GetFrame(1); 
    MethodBase methodBase = stackFrame.GetMethod(); 
    return methodBase.Name; 
} 

我的測試夾具類從基地一個繼承:

[TestFixture] 
public class WhenRegisteringUser : BaseTestFixture 
{ 
} 

和我有以下系統測試:

[Test] 
public void ShouldRegisterThenVerifyEmailThenSignInSuccessfully_WithValidUsersAndSites() 
{ 
    string testMethodName = this.GetCallerMethodName(); 
    // 
} 

當我在Visual Studio中運行它時,它會按照預期返回我的測試方法名稱。

當它由TeamCity運行時,將返回_InvokeMethodFast(),這似乎是TeamCity在運行時爲其自己使用而生成的一種方法。

那麼我怎麼能在運行時獲得測試方法名?

+0

即使從VS啓動時它是否以發佈模式編譯? – 2012-03-12 11:57:54

+1

你是否獲得堆棧中調用的每個方法的彙編信息?也許你可以走上堆棧尋找你的測試組件。 – 2012-03-12 12:00:45

+0

堆棧跟蹤會幫助您查看實際方法名稱是否在調用堆棧的更上方列出。 – 2012-03-12 12:01:03

回答

17

如果您正在使用NUnit的2.5.7/2.6可以使用TestContext class

[Test] 
public void ShouldRegisterThenVerifyEmailThenSignInSuccessfully() 
{ 
    string testMethodName = TestContext.CurrentContext.Test.Name; 
} 
+1

尼斯功能:) – 2012-03-12 12:46:23

+1

MSTest也在其TestContext中公開此信息 – bryanbcook 2012-03-13 05:39:35

+0

它現在可以從TeamCity運行良好,但是當我在Visual Studio中本地運行它時,它會引發對象未初始化的異常。那麼如何讓它在Visual Studio中工作呢? – 2012-03-15 11:19:39

7

如果你不使用NUnit,你可以遍歷堆棧,找到測試方法:

foreach(var stackFrame in stackTrace.GetFrames()) { 
    MethodBase methodBase = stackFrame.GetMethod(); 
    Object[] attributes = methodBase.GetCustomAttributes(typeof(TestAttribute), false); 
    if (attributes.Length >= 1) { 
    return methodBase.Name; 
    } 
} 
return "Not called from a test method"; 
+0

你知道這隻適用於MSTest嗎?或者它可以在NUnit和MSTest上使用? – Yoiku 2015-12-10 16:02:09

+0

您需要將註釋更改爲測試框架的正確註釋。然而,正如接受的答案指出的那樣,NUnit有一個更好的解決方案TestContext。 – 2015-12-15 17:32:12

+0

感謝您的回答,我問,因爲我試圖建立一個FW,我不想限制自己NUnit或MSTest。所以我想我會做的是從底部到頂部循環堆棧,直到找到一個名稱空間不是來自Microsoft或System的方法。我已經嘗試過了,我用MSTest獲得了很好的結果,並從命令行程序調用FW(我得到了主要方法)。 – Yoiku 2015-12-16 18:59:14

5

謝謝你們;我用相結合的辦法,因此現在可以在各種環境中:如果你不使用NUnit或任何其他第三方工具

public string GetTestMethodName() 
{ 
    try 
    { 
     // for when it runs via TeamCity 
     return TestContext.CurrentContext.Test.Name; 
    } 
    catch 
    { 
     // for when it runs via Visual Studio locally 
     var stackTrace = new StackTrace(); 
     foreach (var stackFrame in stackTrace.GetFrames()) 
     { 
      MethodBase methodBase = stackFrame.GetMethod(); 
      Object[] attributes = methodBase.GetCustomAttributes(
             typeof(TestAttribute), false); 
      if (attributes.Length >= 1) 
      { 
       return methodBase.Name; 
      } 
     } 
     return "Not called from a test method"; 
    } 
} 
+0

請注意,在Release版本中,這有時不起作用 - 測試方法可能內聯,而您將無法看到TestAttribute – imaximchuk 2017-10-04 23:18:17

0

。你不會得到TestAttribute

所以你可以這樣做來獲得測試方法的名稱。 使用TestMethodAttribute insted TestAttribute

public string GetTestMethodName() 
    { 
      // for when it runs via Visual Studio locally 
      var stackTrace = new StackTrace(); 
      foreach (var stackFrame in stackTrace.GetFrames()) 
      { 
       MethodBase methodBase = stackFrame.GetMethod(); 
       Object[] attributes = methodBase.GetCustomAttributes(typeof(TestMethodAttribute), false); 
       if (attributes.Length >= 1) 
       { 
        return methodBase.Name; 
       } 
      } 
      return "Not called from a test method"; 
    } 
11

當使用Visual Studio如果您在測試類中添加一個TestContext property你可以很容易地獲得這些信息來運行測試。

[TestClass] 
public class MyTestClass 
{ 
    public TestContext TestContext { get; set; } 

    [TestInitialize] 
    public void setup() 
    { 
     logger.Info(" SETUP " + TestContext.TestName); 
     // .... // 
    } 
}