Reputation: 9394
For our application we have about 4000 Unit-tests which will be automatically executed if we check-in your code to the tfs.
We've changed a lot at our Build-Definition so now it is required that all unit-tests must have the attribute [TestCategory(TestCategories.GatedCheckin)]
to be executed within the gated-checkin.
Unfortunately only 700 Unittest of the 4000 already have this attribute. Now I have to add the attribute to the remaining unit-tests.
Therefor I've written a small VisualStudio-Extension where I can open source file and search for the following regular expression:
^([\t]|[ ])*\[TestMethod\]([\t]|[ ]|[\w\/äÄüÜöÖß])*([\r\n]+)([\t]|[ ])*public
This regular expression just works fine for unit-tests like:
[TestMethod]
public void PathIsValidTest1()
{...}
or
[TestMethod] // another test
public void Calculator_Add_3_And_3_Equals_6_Test()
{...}
But for unittest which also contains another attribute like:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void ThrowOnInputTooLongTest2()
{...}
the regular expression doesn't work.
How can I modify the regular expression, so it matches all Unittests with the [TestMethod]
attribute and not the [TestCategory(TestCategories.GatedCheckin)]
I thougt about a negative lookahead with ?!
but I didn't get it to work.
Any ideas?
I've modified the solution provided by Addison so it looks like:
^[\t ]*\[TestMethod\][ \t\w\/äÄüÜöÖß]*(\n([ \t]*)\[(?!TestCategory\(TestCategories\.GatedCheckin\)).+\][ \t\w\/äÄüÜöÖß]*)?\s+public
If I use this in regex101 it just works fine as you can see here
But if I use this regex in c# with:
string content = File.ReadAllText(file);
Regex regex = new Regex(pattern, RegexOptions.Multiline);
int matchCount = regex.Matches(content).Count;
I only get 2 matches.
Upvotes: 2
Views: 723
Reputation: 8397
Great question!
I managed to do it with this:
^[\t ]*\[TestMethod\][ \t\w\/äÄüÜöÖß]*(\n\[(?!TestCategory\(TestCategories\.GatedCheckin\)).+\][ \t\w\/äÄüÜöÖß]*)*\s+public
I added in another catching field (and simplified the rest of the regex) so that it now checks for any number of other []
AFTER the first [TestMethod]
, and will accept them if and only if none of them are [TestCategory(TestCategories.GatedCheckin)]
.
Here is some C# code to do it:
using System;
using System.Text.RegularExpressions;
namespace Programming {
class Program {
static void Main() {
string content = "namespace MyNameSpace1\n{\n [TestClass]\n public class GetMapPathActionTests\n {\n [TestMethod] // 1\n public void GetMapPath_with_All_Attibutes()\n {\n ...\n }\n [TestMethod] // 2\n [ExpectedException(typeof(DBInstallInfoConverterCrossCheckerRequiredChildNotFoundException))]\n public void GetMapPath_with_Empty_Input()\n {\n \n }\n [TestMethod] // 3\n [ExpectedException(typeof(DBInstallInfoConverterCrossCheckerRequiredChildNotFoundException))]\n public void GetMapPath_with_Empty_Output()\n {\n \n }\n [TestMethod] // 4\n public void GetMapPath_with_Empty()\n {\n \n }\n [TestMethod] // 5\n [ExpectedException(typeof(DBInstallInfoConverterCrossCheckerRequiredChildNotFoundException))]\n public void GetMapPath_with_All_Attibutes_Empty()\n {\n \n }\n }\n}\n";
Regex regex = new Regex(@"^[\t ]*\[TestMethod\][ \t\w\/äÄüÜöÖß]*(\s+\[(?!TestCategory\(TestCategories\.GatedCheckin\)).+\][ \t\w\/äÄüÜöÖß]*)?\s+public", RegexOptions.Multiline);
MatchCollection matches = regex.Matches(content);
foreach (Match match in matches) {
foreach (Capture capture in match.Captures) {
Console.WriteLine(capture.Value);
}
}
}
}
}
Upvotes: 1