我刚刚经历了这个。我们的 VSMDI 定义了几个列表并涵盖了大约 2500 个测试。不幸的是,我找不到一站式实用程序,但我确实设法通过一个快速而肮脏的控制台应用程序结合现有的测试列表迁移工具来完成它:http: //testlistmigration.codeplex.com/
此扩展将从 vsmdi 生成测试播放列表,vsmdi 是一个带有完整测试名称的简单 XML 结构。我的实用程序将播放列表 XML 读入 HeapSet,然后迭代目录中的每个测试文件,解析以 [TestMethod] 开头的每个方法,检查它是否在播放列表中被引用,如果是,则添加测试类别属性。它很丑,但它有效,我在大约一个小时内写了它。
这是 C# 代码……请记住,它是仓促编写的,不考虑美学或最佳实践。它解决了我的问题,如果不是因为这篇文章,它会被扔掉:)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using TestListMigration.Properties;
namespace TestListMigration
{
class Program
{
static void Main(string[] args)
{
HashSet<string> tests = new HashSet<string>();
XmlDocument doc = new XmlDocument();
doc.Load(Settings.Default.Playlist);
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("Add");
foreach (XmlNode node in nodes)
{
tests.Add(node.Attributes["Test"].Value);
}
DirectoryInfo di = new DirectoryInfo(Settings.Default.TestPath);
foreach (FileInfo file in di.GetFiles("*.cs",SearchOption.AllDirectories))
{
var testFileReader =file.OpenText();
string fileContent = testFileReader.ReadToEnd();
testFileReader.Close();
bool dirty = false;
var namespaceMatch = Regex.Match(fileContent, @"namespace ([a-zA-Z\.]*)");
if (namespaceMatch.Success){
string namespaceName = namespaceMatch.Groups[1].Value;
var classNameMatch = Regex.Match(fileContent, @"[\n\r\t ]*(public|internal|public sealed) class ([a-zA-Z0-9\.]*)");
if (classNameMatch.Success)
{
string className = classNameMatch.Groups[2].Value;
StringBuilder newFile = new StringBuilder();
StringReader reader = new StringReader(fileContent);
string line;
while ((line = reader.ReadLine()) != null)
{
newFile.AppendLine(line);
if (line.Contains("[TestMethod]") || line.Contains("[TestMethod()]"))
{
bool methodLineRead = false;
StringBuilder buffer = new StringBuilder();
while (!methodLineRead)
{
line = reader.ReadLine();
buffer.AppendLine(line);
if (line.Contains("void")){
methodLineRead=true;
var testNameMatch = Regex.Match(line, @"[\n\r\t ]*public void ([a-zA-Z\._0-9]*)\(\)");
if (testNameMatch.Success)
{
string fullName = namespaceName + "." + className + "." + testNameMatch.Groups[1].Value;
if (tests.Contains(fullName) && !buffer.ToString().Contains("\t\t[TestCategory(Category." + Settings.Default.Category + ")]"))
{
newFile.AppendLine("\t\t[TestCategory(Category." + Settings.Default.Category + ")]");
dirty = true;
}
}
}
}
newFile.Append(buffer.ToString());
}
}
if (dirty)
{
File.WriteAllText(file.FullName, newFile.ToString());
}
}
}
}
}
}
}