private TestCase GetTestCase(string fullPhpTestName) { // "class::method with data set #0 ('foo', ...)" -> "class::method" int dataSetStrPos = fullPhpTestName.IndexOf(" with data set "); string phpTestName = (dataSetStrPos != -1) ? fullPhpTestName.Substring(0, dataSetStrPos) : fullPhpTestName; string vsTestName = PhpUnitHelper.GetTestNameFromPhp(phpTestName); return(new TestCase(vsTestName, PhpUnitTestExecutor.ExecutorUri, _testRunContext.Source) { DisplayName = fullPhpTestName // Preserve the original data set information if present }); }
private void RunPhpUnitWithExtension(string projectDir, string source, string[] args, Action <Context> initCallback) { if (PhpUnitHelper.Version >= new Version(9, 1)) { // The --extensions CLI argument is available from PHPUnit 9.1 (although it's documented only from 9.3) args = new[] { "--extensions", TestReporterExtension.PhpName }.Concat(args).ToArray(); PhpUnitHelper.Launch(projectDir, source, args, initCallback); } else { // Older PHPUnit versions can receive extensions only in the configuration file, // so we need to create a modified version of the existing one and pass it to PHPUnit. // (or create one from scratch it if it doesn't exist at all) // Create PHPUnit configuration with the extension added string origConfigFile = PhpUnitHelper.TryFindConfigFile(projectDir); var configXml = (origConfigFile != null) ? XElement.Load(origConfigFile) : new XElement("phpunit"); var extensionsEl = configXml.GetOrCreateElement("extensions"); extensionsEl.Add(new XElement("extension", new XAttribute("class", TestReporterExtension.PhpName))); // Store the configuration in a temporary file to pass it to PHPUnit string tempConfigFile = null; try { // The configuration file must be in the same folder as the project in order to work (to load PHP classes properly etc.) tempConfigFile = EnvironmentHelper.GetNonexistingFilePath(projectDir, "phpunit.xml."); // Save the config file without the BOM using (var xmlWriter = new XmlTextWriter(tempConfigFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false))) { configXml.Save(xmlWriter); } args = new[] { "--configuration", tempConfigFile }.Concat(args).ToArray(); PhpUnitHelper.Launch(projectDir, source, args, initCallback); } finally { if (File.Exists(tempConfigFile)) { File.Delete(tempConfigFile); } } } }
private static void ProcessSource(ITestCaseDiscoverySink discoverySink, string source) { string tempTestsXml = null; try { // Use XML output of PHPUnit to gather all the tests and report them string projectDir = EnvironmentHelper.TryFindProjectDirectory(Path.GetDirectoryName(source)); tempTestsXml = Path.GetTempFileName(); PhpUnitHelper.Launch(projectDir, source, new[] { "--list-tests-xml", tempTestsXml }, finishCallback: ctx => ProcessTestsXml(ctx, source, tempTestsXml, discoverySink) ); } finally { if (File.Exists(tempTestsXml)) { File.Delete(tempTestsXml); } } }
private static void ProcessTestsXml(Pchp.Core.Context ctx, string source, string path, ITestCaseDiscoverySink discoverySink) { var testsEl = XElement.Load(path); foreach (var testCaseClassEl in testsEl.Descendants("testCaseClass")) { var phpClassName = testCaseClassEl.Attribute("name").Value; var classInfo = ctx.GetDeclaredType(phpClassName, autoload: false); var filePath = Path.GetFullPath(Path.Combine(ctx.RootPath, classInfo.RelativePath)); // The file might not exist as PHPUnit may mistakenly select classes and methods in its own PHAR, // namely PHPUnit\Framework\WarningTestCase::Warning (happened with PHPUnit 7.5.9) var unit = File.Exists(filePath) ? CodeSourceUnit.ParseCode(File.ReadAllText(filePath), filePath) : null; foreach (var testCaseMethodEl in testCaseClassEl.Descendants("testCaseMethod")) { var methodName = testCaseMethodEl.Attribute("name").Value; var testName = PhpUnitHelper.GetTestNameFromPhp(classInfo, methodName); var testCase = new TestCase(testName, PhpUnitTestExecutor.ExecutorUri, source); if (unit != null) { testCase.DisplayName = $"{classInfo.Name}::{methodName}"; testCase.CodeFilePath = filePath; testCase.LineNumber = GetLineNumber(unit, phpClassName, methodName); } ; ProcessTraits(testCase, testCaseMethodEl.Attribute("groups")?.Value); discoverySink.SendTestCase(testCase); } } }
private void RunSourceTest(string source, IFrameworkHandle frameworkHandle, IEnumerable <TestCase> testCases = null) { try { var args = Array.Empty <string>(); // Optionally filter the test cases by their names if (testCases != null) { var filterItems = from testCase in testCases let testName = PhpUnitHelper.GetPhpTestName(testCase.FullyQualifiedName) select $"^{Regex.Escape(testName)}(\\s|$)"; string filter = $"({string.Join("|", filterItems)})"; args = args.Concat(new[] { "--filter", filter }).ToArray(); } string projectDir = EnvironmentHelper.TryFindProjectDirectory(Path.GetDirectoryName(source)); // Inject our custom extension to report the test results RunPhpUnitWithExtension(projectDir, source, args, ctx => { // Enable Peachpie to create an instance of our custom extension ctx.DeclareType <TestReporterExtension>(); // Pass data to the extension via Context var testRunCtx = new TestRunContext(source, frameworkHandle); ctx.SetProperty(testRunCtx); }); } catch (System.Exception e) { frameworkHandle.SendMessage(TestMessageLevel.Error, e.Message + "\n" + e.StackTrace); } }