diff --git a/.gitignore b/.gitignore
index e280602..8d10ef0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,4 +41,5 @@ bld/
# Cake
tools/**
-!tools/packages.config
\ No newline at end of file
+!tools/packages.config
+/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/TestResults
\ No newline at end of file
diff --git a/Developer Samples/CommandLineTools/CommandLineTools.sln b/Developer Samples/CommandLineTools/CommandLineTools.sln
index bacba67..194ebd7 100644
--- a/Developer Samples/CommandLineTools/CommandLineTools.sln
+++ b/Developer Samples/CommandLineTools/CommandLineTools.sln
@@ -1,37 +1,37 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.421
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PromoteRuleApp", "PromoteRuleApp\PromoteRuleApp.csproj", "{62314AB8-B6B4-4480-92F8-7CAA32115C87}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildIrJsRuleApp", "BuildIrJsRuleApp\BuildIrJsRuleApp.csproj", "{23CF13F1-F24F-4C0A-8299-E95683A53435}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteTests", "ExecuteTests\ExecuteTests.csproj", "{9ABF0D22-46AD-49DE-B122-3180FDA2F391}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Release|Any CPU.Build.0 = Release|Any CPU
- {23CF13F1-F24F-4C0A-8299-E95683A53435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {23CF13F1-F24F-4C0A-8299-E95683A53435}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {23CF13F1-F24F-4C0A-8299-E95683A53435}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {23CF13F1-F24F-4C0A-8299-E95683A53435}.Release|Any CPU.Build.0 = Release|Any CPU
- {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {B5723BBE-B898-46F7-A7D8-9434269D523E}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PromoteRuleApp", "PromoteRuleApp\PromoteRuleApp.csproj", "{62314AB8-B6B4-4480-92F8-7CAA32115C87}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildIrJsRuleApp", "BuildIrJsRuleApp\BuildIrJsRuleApp.csproj", "{23CF13F1-F24F-4C0A-8299-E95683A53435}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteTests", "ExecuteTests\ExecuteTests.csproj", "{9ABF0D22-46AD-49DE-B122-3180FDA2F391}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {62314AB8-B6B4-4480-92F8-7CAA32115C87}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23CF13F1-F24F-4C0A-8299-E95683A53435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23CF13F1-F24F-4C0A-8299-E95683A53435}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23CF13F1-F24F-4C0A-8299-E95683A53435}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23CF13F1-F24F-4C0A-8299-E95683A53435}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9ABF0D22-46AD-49DE-B122-3180FDA2F391}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B5723BBE-B898-46F7-A7D8-9434269D523E}
+ EndGlobalSection
+EndGlobal
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite.sln b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite.sln
new file mode 100644
index 0000000..0367cf0
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite.sln
@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MstestWrapperForTestsuite", "MstestWrapperForTestsuite\MstestWrapperForTestsuite.csproj", "{C0B8E5EA-99ED-46E9-8165-2537E4FA2034}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9812F383-F8C8-4DAE-B3B9-CC678BEADC65}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C0B8E5EA-99ED-46E9-8165-2537E4FA2034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C0B8E5EA-99ED-46E9-8165-2537E4FA2034}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C0B8E5EA-99ED-46E9-8165-2537E4FA2034}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C0B8E5EA-99ED-46E9-8165-2537E4FA2034}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {29017B77-429B-4ACD-A848-AFC2AB4B2FEA}
+ EndGlobalSection
+EndGlobal
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuite.cs b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuite.cs
new file mode 100644
index 0000000..285a632
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuite.cs
@@ -0,0 +1,33 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MstestWrapperForTestsuite
+{
+ [TestClass]
+ public class DataDrivenWrapperForTestsuite : DataDrivenWrapperForTestsuiteBase
+ {
+ [DataTestMethod]
+ [DataSource(
+ "Microsoft.VisualStudio.TestTools.DataSource.CSV",
+ "|DataDirectory|\\data\\testsuitelist.csv",
+ "testsuitelist#csv",
+ DataAccessMethod.Sequential)]
+ [DeploymentItem("..\\..\\data")]
+ public void TestInRuleTestSuiteFromCsvDataSource()
+ {
+ var ruleAppFilePath = TestContext.DataRow["RuleAppFilePath"].ToString();
+ var testSuiteFilePath = TestContext.DataRow["TestSuiteFilePath"].ToString();
+
+ ExecuteInRuleTestSuite(ruleAppFilePath, testSuiteFilePath);
+ }
+
+ [DataTestMethod]
+ [FolderConventionDataSource(ruleAppPath: "ruleapp", testSuitePath: "testsuite")]
+ [DeploymentItem("..\\..\\data")]
+ public void TestInRuleFromFolderConvention(string ruleApp, string testSuite, string ruleAppFilePath, string testSuiteFilePath)
+ {
+ TestContext.WriteLine($"{ruleApp} - {testSuite}");
+
+ ExecuteInRuleTestSuite(ruleAppFilePath, testSuiteFilePath);
+ }
+ }
+}
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuiteBase.cs b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuiteBase.cs
new file mode 100644
index 0000000..e087ff5
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/DataDrivenWrapperForTestsuiteBase.cs
@@ -0,0 +1,79 @@
+using InRule.Repository;
+using InRule.Repository.Regression;
+using InRule.Runtime;
+using InRule.Runtime.Testing.Regression;
+using InRule.Runtime.Testing.Regression.Runtime;
+using InRule.Runtime.Testing.Session;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.IO;
+
+namespace MstestWrapperForTestsuite
+{
+ [TestClass]
+ public abstract class DataDrivenWrapperForTestsuiteBase
+ {
+ public TestContext TestContext { get; set; }
+
+ protected TestResultCollection RunTestSuite(string ruleAppFilePath, string testSuiteFilePath)
+ {
+ if (!File.Exists(ruleAppFilePath))
+ {
+ throw new FileNotFoundException("ERROR: Rule App file not found at " + ruleAppFilePath);
+ }
+ if (!File.Exists(testSuiteFilePath))
+ {
+ throw new FileNotFoundException("ERROR: Test Suite file not found at " + testSuiteFilePath);
+ }
+
+ var ruleApp = new FileSystemRuleApplicationReference(ruleAppFilePath);
+ RuleApplicationDef ruleAppDef = ruleApp.GetRuleApplicationDef();
+
+ TestSuiteDef suite = TestSuiteDef.LoadFrom(new ZipFileTestSuitePersistenceProvider(testSuiteFilePath));
+ suite.ActiveRuleApplicationDef = ruleAppDef;
+
+ TestResultCollection results;
+ using (TestingSessionManager manager = new TestingSessionManager(new InProcessConnectionFactory()))
+ {
+ var session = new RegressionTestingSession(manager, suite);
+ results = session.ExecuteAllTests();
+ }
+
+ return results;
+ }
+
+ protected void ExecuteInRuleTestSuite(string ruleAppFilePath, string testSuiteFilePath)
+ {
+ if (string.IsNullOrEmpty(testSuiteFilePath) || !File.Exists(testSuiteFilePath))
+ {
+ Assert.Inconclusive($"TestSuite does not exist for {ruleAppFilePath}");
+ }
+ else
+ {
+ RunTestSuiteAndReportToContext(ruleAppFilePath, testSuiteFilePath);
+ }
+ }
+
+ private void RunTestSuiteAndReportToContext(string ruleAppFilePath, string testSuiteFilePath)
+ {
+ var testResultCollection = RunTestSuite(ruleAppFilePath, testSuiteFilePath);
+
+ TestContext.WriteLine("Using Rule App " + ruleAppFilePath);
+ TestContext.WriteLine("Using Test Suite " + testSuiteFilePath);
+
+ foreach (var result in testResultCollection)
+ {
+ if (result.RuntimeErrorMessage != null)
+ {
+ TestContext.WriteLine($"ERROR: Failed to execute test {result.TestDef.DisplayName}: {result.RuntimeErrorMessage}");
+ }
+ else
+ {
+ result.ReportAssertionResultsToContext(TestContext);
+ }
+
+ Assert.AreEqual(true, result.Passed);
+ Assert.IsNull(result.RuntimeErrorMessage);
+ }
+ }
+ }
+}
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/MstestWrapperForTestsuite.csproj b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/MstestWrapperForTestsuite.csproj
new file mode 100644
index 0000000..6c15876
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/MstestWrapperForTestsuite.csproj
@@ -0,0 +1,73 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C0B8E5EA-99ED-46E9-8165-2537E4FA2034}
+ Library
+ Properties
+ MstestWrapperForTestsuite
+ MstestWrapperForTestsuite
+ v4.7.2
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 15.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5.4.0
+
+
+ 5.4.0
+
+
+ 2.1.1
+
+
+ 2.1.1
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/Properties/AssemblyInfo.cs b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a3c861a
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("MstestWrapperForTestsuite")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MstestWrapperForTestsuite")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("c0b8e5ea-99ed-46e9-8165-2537e4fa2034")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/MockWithoutTestsuiteApp.ruleappx b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/MockWithoutTestsuiteApp.ruleappx
new file mode 100644
index 0000000..a500b10
Binary files /dev/null and b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/MockWithoutTestsuiteApp.ruleappx differ
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/RectangleApp.ruleappx b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/RectangleApp.ruleappx
new file mode 100644
index 0000000..035f07d
Binary files /dev/null and b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/RectangleApp.ruleappx differ
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/SquareApp.ruleappx b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/SquareApp.ruleappx
new file mode 100644
index 0000000..a500b10
Binary files /dev/null and b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/ruleapp/SquareApp.ruleappx differ
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/rectangleApp/Rectangle.testsuite b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/rectangleApp/Rectangle.testsuite
new file mode 100644
index 0000000..4a4863e
Binary files /dev/null and b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/rectangleApp/Rectangle.testsuite differ
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/squareApp/Square.testsuite b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/squareApp/Square.testsuite
new file mode 100644
index 0000000..563c64c
Binary files /dev/null and b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuite/squareApp/Square.testsuite differ
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuitelist.csv b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuitelist.csv
new file mode 100644
index 0000000..aaea4d5
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/data/testsuitelist.csv
@@ -0,0 +1,3 @@
+RuleAppFilePath,TestSuiteFilePath
+ruleapp\RectangleApp.ruleappx,testsuite\rectangleApp\Rectangle.testsuite
+ruleapp\SquareApp.ruleappx,testsuite\squareApp\Square.testsuite
diff --git a/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/helpers/CustomDataSourceAttribute.cs b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/helpers/CustomDataSourceAttribute.cs
new file mode 100644
index 0000000..4ce1ce9
--- /dev/null
+++ b/Developer Samples/MstestWrapperForTestsuite/MstestWrapperForTestsuite/helpers/CustomDataSourceAttribute.cs
@@ -0,0 +1,75 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+
+namespace MstestWrapperForTestsuite
+{
+ public class FolderConventionDataSourceAttribute : Attribute, ITestDataSource
+ {
+ public string RuleAppPath { get; }
+ public string TestSuitePath { get; }
+
+ ///
+ /// By convention all the testSuite files related to a ruleapp
+ /// will be placed under a subfolder of testSuitePath named after the ruleapp
+ /// for example, if ruleAppPath = "ruleapp", testSuitePath = "testsuite"
+ /// the folder structure will be as follows
+ /// ├───ruleapp
+ /// │ RectangleApp.ruleappx
+ /// │ SquareApp.ruleappx
+ /// │
+ /// └───testsuite
+ /// ├───rectangleApp
+ /// │ Rectangle.testsuite
+ /// │
+ /// └───squareApp
+ /// Square.testsuite
+ ///
+ /// The path to the ruleApp files
+ /// The path to the testSuite files
+ public FolderConventionDataSourceAttribute(string ruleAppPath, string testSuitePath)
+ {
+ RuleAppPath = ruleAppPath;
+ TestSuitePath = testSuitePath;
+ }
+
+ public IEnumerable