Как получить атрибуты метода unit test во время выполнения из тестового прогона NUnit?
Я храню различную информацию о данном тесте (идентификаторы для нескольких систем отслеживания ошибок) в атрибуте, подобном этому:
[TestCaseVersion("001","B-8345","X543")]
public void TestSomethingOrOther()
Чтобы получить эту информацию в ходе теста, я написал код ниже:
public string GetTestID()
{
StackTrace st = new StackTrace(1);
StackFrame sf;
for (int i = 1; i <= st.FrameCount; i++)
{
sf = st.GetFrame(i);
if (null == sf) continue;
MethodBase method = sf.GetMethod();
if (method.GetCustomAttributes(typeof(TestAttribute), true).Length == 1)
{
if (method.GetCustomAttributes(typeof(TestCaseVersion), true).Length == 1)
{
TestCaseVersion tcv =
sf.GetMethod().GetCustomAttributes(typeof(TestCaseVersion), true).OfType<TestCaseVersion>()
.First();
return tcv.TestID;
}
}
}
Проблема заключается в том, что при выполнении тестов через NUnit в режиме Release метод, который должен иметь имя теста и эти атрибуты, заменяется следующим:
System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at NUnit.Core.Reflect.InvokeMethod(MethodInfo method, Object fixture, Object[] args)
UPDATE
Для всех, кто заинтересован, я завершил реализацию кода следующим образом (чтобы можно было получить доступ к любому из значений атрибутов без изменения какого-либо существующего кода, который использует атрибут TestCaseVersion:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method, AllowMultiple = false)]
public class TestCaseVersion : PropertyAttribute
{
public TestCaseVersion(string testCaseCode, string story, string task, string description)
{
base.Properties.Add("TestId", testCaseCode);
base.Properties.Add("Description", description);
base.Properties.Add("StoryId", story);
base.Properties.Add("TaskId", task);
}
}
public string GetTestID()
{
return TestContext.CurrentContext.Test.Properties["TestId"];
}
Ответы
Ответ 1
Если у вас все в порядке с строкой версии тестового примера (т.е. "001, B-8345, X543"
вместо "001","B-8345","X543"
), вы должны использовать TestContext, доступный в NUnit 2.5.7 и выше.
В частности, вы можете определить и использовать тестовый контекст Property атрибут TestCaseVersion следующим образом:
[Test, Property("TestCaseVersion", "001, B-8345, X543")]
public void TestContextPropertyTest()
{
Console.WriteLine(TestContext.CurrentContext.Test.Properties["TestCaseVersion"]);
}
ОБНОВЛЕНИЕ. Если вы хотите использовать многозначное представление версии тестового примера, вы можете определить несколько свойств, например:
[Test, Property("MajorVersion", "001"),
Property("MinorVersion", "B-8345"), Property("Build", "X543")]
public void TestContextPropertyTest()
{
Console.WriteLine(TestContext.CurrentContext.Test.Properties["MajorVersion"]);
Console.WriteLine(TestContext.CurrentContext.Test.Properties["MinorVersion"]);
Console.WriteLine(TestContext.CurrentContext.Test.Properties["Build"]);
}
Ответ 2
Возможно, я не понимаю вашу идею, но почему бы не использовать гораздо более простое решение?
[TestCase(TestName = "001, B-8345, X543")]
public void TestSomethingOrOther()