/// <summary>
        /// Discovers tests in the application and maps routes to allow them to be called over HTTP.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="configureTargets">A delegate to configure the test targets.</param>
        /// <param name="baseUri">The base URI segment that the tests will be routed under.</param>
        /// <param name="testTypes">The Types to map routes for. If omitted, all discovered implementations of <see cref="IMonitoringTest" /> will be routed.</param>
        /// <param name="handler">A message handler to handle test requests, if you would like to provide authentication, logging, or other functionality during calls to monitoring tests.</param>
        /// <param name="testUiScriptUrl">The location of the test UI script.</param>
        /// <param name="testUiLibraryUrls">The locations of any libraries the UI script depends on</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">configuration</exception>
        public static HttpConfiguration MapTestRoutes(
            this HttpConfiguration configuration,
            Action<TestTargetRegistry> configureTargets = null,
            string baseUri = "tests",
            IEnumerable<Type> testTypes = null,
            HttpMessageHandler handler = null,
            string testUiScriptUrl = null,
            IEnumerable<string> testUiLibraryUrls = null)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (!Trace.Listeners.OfType<TracingFilter.TraceListener>().Any())
            {
                var traceListener = new TracingFilter.TraceListener();
                Trace.Listeners.Add(traceListener);
                Instrumentation.Log.EntryPosted += (_, args) => traceListener.WriteLine(args.LogEntry.ToLogString());
            }

            // set up specialized handling on the specified routes
            configuration.Filters.Add(new TestErrorFilter(baseUri));
            if (!string.IsNullOrEmpty(testUiScriptUrl) &&
                Uri.IsWellFormedUriString(testUiScriptUrl, UriKind.RelativeOrAbsolute))
            {
                configuration.TestUiUriIs(testUiScriptUrl);
            }
            var testUiLibraryUrlsArray = testUiLibraryUrls
                .IfNotNull()
                .Then(a => a.Where(u => !string.IsNullOrEmpty(u)
                                        && Uri.IsWellFormedUriString(u, UriKind.RelativeOrAbsolute))
                    .ToArray())
                .Else(() => new string[] {});
            configuration.TestLibraryUrisAre(testUiLibraryUrlsArray);

            var testRootRouteTemplate = baseUri.AppendSegment("{environment}/{application}");
            configuration.RootTestUriIs(baseUri);

            // set up test discovery routes
            configuration.Routes.MapHttpRoute(
                TestRootRouteName,
                testRootRouteTemplate,
                defaults: new
                {
                    controller = "MonitoringTest",
                    action = "tests",
                    application = RouteParameter.Optional,
                    environment = RouteParameter.Optional
                },
                constraints: null,
                handler: handler);

            // set up test execution routes
            var targetRegistry = new TestTargetRegistry(configuration);
            configuration.TestTargetsAre(targetRegistry);
            configureTargets?.Invoke(targetRegistry);

            testTypes = testTypes ?? Discover.ConcreteTypes()
                .DerivedFrom(typeof (IMonitoringTest));

            var testDefinitions = testTypes.GetTestDefinitions();
            configuration.TestDefinitionsAre(testDefinitions);

            testDefinitions.Select(p => p.Value)
                           .ForEach(test =>
                           {
                               var targetConstraint = new TargetConstraint(test);
                               
                               targetRegistry.ForEach(target => { Task.Run(() => targetConstraint.Match(target)); });

                               configuration.Routes.MapHttpRoute(
                                   test.RouteName,
                                   testRootRouteTemplate.AppendSegment(test.TestName),
                                   defaults: new
                                   {
                                       controller = "MonitoringTest",
                                       action = "run",
                                       testName = test.TestName
                                   },
                                   constraints: new
                                   {
                                       tag = new TagConstraint(test),
                                       application = new ApplicationConstraint(test),
                                       environment = new EnvironmentConstraint(test),
                                       target = targetConstraint
                                   },
                                   handler: handler
                                   );
                           });

            return configuration;
        }
 internal static void TestTargetsAre(
     this HttpConfiguration configuration,
     TestTargetRegistry targets) =>
         configuration.Properties["Its.Log.Monitoring.TestTargets"] = targets;