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);
                }
            }
        }