我想在運行之前報告它們,並且可以選擇通過shell腳本運行單個測試,而無需管理類別。我們有一些非託管代碼會使進程處於不良狀態,並且有時很高興能夠按照每個nunit控制檯運行單獨運行每個測試。nunit-console可以列出測試夾具中的所有測試名稱嗎?
回答
nunit-console仍然不支持此選項。然而,使用反射來獲取測試用例列表是非常簡單的。在非常基礎的層面上,您需要列出所有public class
的public
方法以及相應的[Test]/[TestFixture]
屬性。根據測試的結構,您可能需要執行額外的過濾,例如刪除標記爲[Ignore]
屬性的任何測試,或考慮基本類中的測試方法。
在基本層面,代碼會是這個樣子:
// Load the assembly containing your fixtures
Assembly a = Assembly.LoadFrom(assemblyName);
// Foreach public class that is a TestFixture and not Ignored
foreach (var c in a.GetTypes()
.Where(x=>x.IsPublic
&& (x.GetCustomAttributes(typeof(NUnit.Framework.TestFixtureAttribute)).Count() > 0)
&& (x.GetCustomAttributes(typeof(NUnit.Framework.IgnoreAttribute)).Count() ==0)))
{
// For each public method that is a Test and not Ignored
foreach (var m in c.GetMethods()
.Where(x=>x.IsPublic
&& (x.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute)).Count() > 0)
&& (x.GetCustomAttributes(typeof(NUnit.Framework.IgnoreAttribute)).Count() ==0)))
{
// Print out the test name
Console.WriteLine("{0}.{1}", c.ToString(), m.Name);
// Alternately, print out the command line to run test case using nunit-console
//Console.WriteLine("nunit-console /run:{0}.{1} {2}", c.ToString(), m.Name, assemblyName);
}
}
顯然你可以簡化這個有點,如果你只是想從一個特定的TestFixture
的測試方法。
正如評論中所說,如果您需要關注其他NUnit屬性,例如TestCase
和TestCaseSource
,這會變得更加複雜。我修改了下面的代碼來支持這些屬性的一些功能。
static void PrintTestNames(string assemblyName) {
Assembly assembly = Assembly.LoadFrom(assemblyName);
foreach (var fixture in assembly.GetTypes().Where(x => x.IsPublic
&& (x.GetCustomAttributes(typeof(TestFixtureAttribute)).Count() > 0)
&& (x.GetCustomAttributes(typeof(IgnoreAttribute)).Count() == 0))) {
foreach(var method in fixture.GetMethods().Where(x=>x.IsPublic
&& (x.GetCustomAttributes(typeof(IgnoreAttribute)).Count() == 0)
&& ((x.GetCustomAttributes(typeof(TestAttribute)).Count() > 0)
|| (x.GetCustomAttributes(typeof(TestCaseAttribute)).Count() > 0)
|| (x.GetCustomAttributes(typeof(TestCaseSourceAttribute)).Count() > 0))
)) {
var testAttributes = method.GetCustomAttributes(typeof(TestAttribute)) as IEnumerable<TestAttribute>;
var caseAttributes = method.GetCustomAttributes(typeof(TestCaseAttribute)) as IEnumerable<TestCaseAttribute>;
var caseSourceAttributes = method.GetCustomAttributes(typeof(TestCaseSourceAttribute)) as IEnumerable<TestCaseSourceAttribute>;
if (caseAttributes.Count() > 0) {
foreach(var testCase in caseAttributes) {
if (!string.IsNullOrEmpty(testCase.TestName)) {
PrintTestName(fixture.ToString(), testCase.TestName);
}
else {
string arguments = ExtractArguments(testCase.Arguments);
PrintTestName(fixture.ToString(), method.Name + arguments);
}
}
}
else if (caseSourceAttributes.Count() > 0) {
foreach (var testCase in caseSourceAttributes) {
var sourceName = testCase.SourceName;
if (!string.IsNullOrEmpty(sourceName)) {
var staticMember = fixture.GetField(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var instanceMember = fixture.GetField(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
var staticMethodMember = fixture.GetMethod(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var instanceMethodMember = fixture.GetMethod(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
var staticPropMember = fixture.GetProperty(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var instancePropMember = fixture.GetProperty(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
IEnumerable memberValues;
if (null != staticMember) {
memberValues = staticMember.GetValue(null) as IEnumerable;
}
else if (null != instanceMember) {
var instance = Activator.CreateInstance(fixture);
memberValues = instanceMember.GetValue(instance) as IEnumerable;
} else if(null != staticMethodMember) {
memberValues = staticMethodMember.Invoke(null,new object [0]) as IEnumerable;
}
else if (null != instanceMethodMember) {
var instance = Activator.CreateInstance(fixture);
memberValues = instanceMethodMember.Invoke(instance, new object[0]) as IEnumerable;
}
else if (null != staticPropMember) {
memberValues = staticPropMember.GetValue(null) as IEnumerable;
}
else if (null != instancePropMember) {
var instance = Activator.CreateInstance(fixture);
memberValues = instancePropMember.GetValue(instance) as IEnumerable;
}
else {
Console.WriteLine("*** Ooops...Looks like I don't know how to get {0} for fixture {1}", sourceName, fixture.ToString());
continue;
}
foreach (var memberValue in memberValues) {
if (null != memberValue as IEnumerable) {
PrintTestName(fixture.ToString(), method.Name + ExtractArguments(memberValue as IEnumerable));
}
else {
PrintTestName(fixture.ToString(), method.Name + "(" + memberValue.ToString() + ")");
}
}
} else {
Console.WriteLine("*** Ooops...Looks like I don't know how to handle test {0} for fixture {1}", method.Name, fixture.ToString());
}
}
}
else {
PrintTestName(fixture.ToString(), method.Name);
}
}
}
}
static string ExtractArguments(IEnumerable arguments) {
string caseArgs = "(";
bool first = true;
foreach (var arg in arguments) {
if (first) first = false;
else caseArgs += ",";
caseArgs += Convert.ToString(arg);
}
return caseArgs + ")";
}
static void PrintTestName(string fixture, string testName) {
Console.WriteLine("{0}.{1}", fixture, testName);
//Console.WriteLine("nunit-console /run:{0}.{1} {2}", fixture, testName, assemblyName);
}
如果你通過上面的代碼,你可能會注意到,我已經處理功能,其中TestCaseSource
的測試是一個字符串,命名的屬性/方法/場。您還會注意到雖然代碼還有更多代碼,但它仍然非常簡單易用,所以如果您使用的是TestCaseSource的替代版本,或者您還有其他NUnit屬性,則可以輕鬆擴展它沒有照顧。
爲上面添加一個計數器也是很容易的,這樣您就可以獲得相當數量的測試結果,並且與nunit控制檯運行的測試數量相當。
這將獲得基礎知識,但如果您使用某些可以自動從不同輸入生成測試的更高級屬性,那麼您的運氣不好! – 2015-06-02 14:28:56
@SebastianGood我已經添加了對TestCase +一些TestCaseSource排列的支持。擴展代碼以處理其他TestCaseSource選項(或其他屬性,我還沒有找到)應該是直截了當,如果您使用替代的,但我會留下*閱讀*的練習。 – forsvarir 2015-06-03 06:35:45
您還需要考慮測試類從具有這些屬性的(抽象)基類繼承的情況。然後需要調整計數多次運行相同的測試方法, – WebDancer 2017-03-24 10:39:38
現在有--explore
命令行選項,可用於列出所有測試用例而不運行測試。更具體地說
nunit3-console.exe MyProject.dll --explore
欲瞭解更多信息:https://github.com/nunit/docs/wiki/Console-Command-Line#description
- 1. 沒有夾具的ScalaTest測試名稱?
- 2. Google測試夾具
- 3. 測試名稱與測試AssemblyCleanup
- 4. 在C#中如果我可以第一次測試停止其他測試或執行所有測試嗎?
- 5. 如何在測試報告中包含測試用例所有者名稱
- 6. 的Xcode 8測試版:可測試名稱必須是唯一
- 7. 如何使用REST API列出teamcity中的所有測試名稱
- 8. 具有測試
- 9. 測試類可以有屬性嗎?
- 10. 有人可以解釋爲什麼MySQL時,名稱=「測試」返回兩個值:「測試」和「測試」
- 11. 有黑盒測試的自動化測試工具嗎?
- 12. 測試夾具數據
- 13. 通夾具,測試類pytest
- 14. D2單元測試夾具
- 15. 單元測試名稱很重要嗎?
- 16. MS測試,嘗試將我的測試名稱插入測試功能
- 17. Visual Studio 2010中測試方法的自定義測試名稱
- 18. Firebase測試實驗室可以運行Monkeyrunner測試嗎?
- 19. 你可以簡介Ms測試集成測試嗎?
- 20. MFC gui可以測試谷歌測試嗎?
- 21. 您可以使用Facebook「測試用戶」測試Messenger Bot嗎?
- 22. 我可以使用機架測試進行部署測試嗎?
- 23. 使用junit測試可以測試本地值嗎?
- 24. 如何管理用於端到端測試的測試夾具?
- 25. QTest獲得測試名稱
- 26. 有什麼方法可以測試UIAutomation測試的代碼覆蓋率嗎?
- 27. 我可以確保所有測試都包含測試/單元中的斷言嗎?
- 28. 我可以在Angular2 Testbed中使用`tape`測試工具嗎?
- 29. 具有可變數量測試的PyUnit
- 30. 如何調用和測試具有相同名稱的方法?
'NUnit控制檯MyAssembly.dll程序/ labels'將顯示所有的測試,因爲他們跑,但我是正確的思維,你想要的是獲取預先列出,然後提示用戶(或將它們添加到'/ runlist ='文件中)? 不想使用類別的理由是什麼? – ClickRick 2014-04-08 00:29:49
我們希望他們提前,正確。這裏的關鍵是我們希望一次運行一個,即每次運行一次,一次又一次地運行nunit-console。我們改變了組件,以至於我們不再需要這樣做,但是我仍然很驚訝,沒有看到這方面的答案。 – 2014-04-10 04:14:50
如果這仍然是你的問題,我會試着用他們的EventListener類來看看(參見http://imistaken.blogspot.co.uk/2009/03/nunit-extensions-adding-logic-at-run .html作爲例子),看看你是否可以通過這種方式獲得列表,但是這要依靠能夠抑制當時測試的實際運行,而這是我不經過嘗試就不知道的。 – ClickRick 2014-04-10 12:41:24