问题
I store various information about a given test (IDs for multiple bug tracking systems) in an attribute like so:
[TestCaseVersion("001","B-8345","X543")]
public void TestSomethingOrOther()
In order to fetch this information during the course of a test, I wrote the below code:
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;
}
}
}
The problem is that when running tests through NUnit in Release mode, the method which should have the test name and these attributes is replaced by the following:
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 For anyone who is interested, I wound up implementing the code in the following way (so that any of the attribute values could be accessed, without changing any of the existing code that uses TestCaseVersion attribute:
[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:
If you are OK with having a single-valued test case version string (i.e. "001, B-8345, X543"
instead of "001","B-8345","X543"
), you should be able to make use of the TestContext functionality available in NUnit 2.5.7 and higher.
Specifically, you could define and use a test context Property attribute TestCaseVersion like this:
[Test, Property("TestCaseVersion", "001, B-8345, X543")]
public void TestContextPropertyTest()
{
Console.WriteLine(TestContext.CurrentContext.Test.Properties["TestCaseVersion"]);
}
UPDATE BTW, If you do want to use a multi-valued representation of the test case version, you could define multiple properties, like this:
[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:
May be I don't understand your idea, but why not to use much simpler solution?
[TestCase(TestName = "001, B-8345, X543")]
public void TestSomethingOrOther()
来源:https://stackoverflow.com/questions/11762648/how-to-get-unit-test-method-attributes-at-runtime-from-within-an-nunit-test-run