/// <summary>
        /// Performs an action for all the databases configured from all sources.
        /// </summary>
        /// <param name="targetType">The type of the class currently running a test.</param>
        /// <param name="dbAttributes">
        /// All the <see cref="UsesDatabasesAttribute"/> attributes on the target class.</param>
        /// <param name="provider">The current provider for which connections are being provided through.</param>
        /// <param name="action">The action to execute for each database.</param>
        private static void ExecuteActionForAllDatabases(
            Type targetType,
            IEnumerable <UsesDatabasesAttribute> dbAttributes,
            IDatabaseProvider <IDbConnection> provider,
            Action <string> action)
        {
            List <Action> dbSetupActions           = new List <Action>();
            List <string> alreadyActionedDatabases = new List <string>();

            if (dbAttributes.Any())
            {
                // Perform the action for all the databases defined in the UsesDatabaseAttribute.
                foreach (var databaseName in dbAttributes.First().Databases)
                {
                    dbSetupActions.Add(() => action(databaseName));
                    alreadyActionedDatabases.Add(databaseName);
                }
            }

            // Perform the action for all the databases defined in the application configuration file.
            ProviderConfigurationBase providerConfig =
                (ProviderConfigurationBase)ConfigurationManager.GetSection("dbTestMonkey/" + provider.ConfigurationSectionName);

            foreach (var databaseName in providerConfig.Databases
                     .Cast <DatabaseConfiguration>()
                     .Select(dc => dc.DatabaseName)
                     .Where(dn => !alreadyActionedDatabases.Any(asd => asd == dn)))
            {
                dbSetupActions.Add(() => action(databaseName));
                alreadyActionedDatabases.Add(databaseName);
            }

            // Finally perform the action for all databases defined on connection properties in the class.
            foreach (var connectionAttribute in targetType
                     .GetProperties()
                     .Where(pi => pi.CustomAttributes.Any(a => a.AttributeType.Name == "ConnectionAttribute"))
                     .Select(pi => pi.GetCustomAttribute(typeof(ConnectionAttribute), true)))
            {
                var connAttribute = connectionAttribute as ConnectionAttribute;

                if (connAttribute.TargetDatabaseName != null &&
                    !alreadyActionedDatabases.Contains(connAttribute.TargetDatabaseName))
                {
                    dbSetupActions.Add(() => action(connAttribute.TargetDatabaseName));
                    alreadyActionedDatabases.Add(connAttribute.TargetDatabaseName);
                }
            }

            GlobalConfiguration globalConfig =
                (GlobalConfiguration)ConfigurationManager.GetSection("dbTestMonkey/global");

            if (globalConfig.UseParallelInitialisation)
            {
                Parallel.Invoke(dbSetupActions.ToArray());
            }
            else
            {
                dbSetupActions.ForEach(act => act.Invoke());
            }
        }
        /// <summary>
        /// Examines an object to determine the correct property to populate with a database connection.
        /// </summary>
        /// <param name="targetObject">The object to examine for best match properties.</param>
        /// <param name="databaseName">The name of the database the connection will be to.</param>
        /// <param name="providerConfig">
        /// An object representing the app.config configuration for the current provider.</param>
        /// <returns>A property information object containing the best match.</returns>
        private static PropertyInfo FindBestMatchConnectionProperty(
            object targetObject,
            string databaseName,
            ProviderConfigurationBase providerConfig)
        {
            var properties = targetObject.GetType().GetProperties(
                BindingFlags.SetProperty |
                BindingFlags.Public |
                BindingFlags.Instance |
                BindingFlags.IgnoreCase);

            string preConfiguredConnectionPropertyName = null;

            if (providerConfig.Databases.Cast <DatabaseConfiguration>()
                .Any(d => d.DatabaseName == databaseName && !string.IsNullOrWhiteSpace(d.ConnectionPropertyName)))
            {
                preConfiguredConnectionPropertyName =
                    providerConfig.Databases.Cast <DatabaseConfiguration>().First().ConnectionPropertyName;
            }

            return(properties.FirstOrDefault(prop =>
            {
                if (string.IsNullOrWhiteSpace(preConfiguredConnectionPropertyName))
                {
                    return prop.GetCustomAttributes().Cast <Attribute>().RequiresConnectionToDatabase(databaseName) ||
                    prop.Name == UppercaseFirstChar(databaseName) + "Connection";
                }
                else
                {
                    return prop.Name == preConfiguredConnectionPropertyName;
                }
            }));
        }
Exemple #3
0
        public void LoadSettings(ProviderConfigurationBase uc, string providerName)
        {
            _uc = uc;

            this.Title = Properties.Resources.ProviderSettingsTitle + providerName;
            //spContent.Children.Add(uc);
        }
        /// <summary>
        /// Method called before a test is executed.
        /// </summary>
        /// <param name="sender">The object which called this method.</param>
        /// <param name="methodBase">Contextual information about the method which called this method.</param>
        public static void BeforeTest(object sender, MethodBase methodBase, Action <string> logAction)
        {
            logAction("Preparing to execute before test DbTestMonkey actions.");

            var dbAttributes = methodBase
                               .DeclaringType
                               .GetCustomAttributes(typeof(UsesDatabasesAttribute), true)
                               .Cast <UsesDatabasesAttribute>();

            List <PropertyInfo> activeConnectionProperties = new List <PropertyInfo>();

            Type providerType = null;

            GlobalConfiguration globalConfig =
                (GlobalConfiguration)ConfigurationManager.GetSection("dbTestMonkey/global");

            if (dbAttributes.Count() > 1)
            {
                throw new NotImplementedException(
                          "Multiple UsesDatabaseAttributes have been defined on the test class. " +
                          "Only one attribute is currently supported at this time.");
            }
            else if (globalConfig != null && globalConfig.DeployDatabasesEachClass && dbAttributes.Any())
            {
                providerType = dbAttributes.First().ProviderType;
                logAction("Using the provider type " + providerType.Name + " as configured in the UsesDatabasesAttribute.");
            }
            else
            {
                if (globalConfig == null || string.IsNullOrWhiteSpace(globalConfig.DefaultDbProvider))
                {
                    throw new InvalidOperationException(
                              "DefaultDbProvider global configuration setting has not been configured but it is required for the current configuration.");
                }

                providerType = globalConfig.DefaultDbProviderType;
                logAction("Using the provider type " + providerType.Name + " as configured in app.config.");
            }

            var provider = Activator.CreateInstance(providerType) as IDatabaseProvider <IDbConnection>;

            if (provider == null)
            {
                throw new InvalidOperationException(
                          "Provider type " + providerType.FullName +
                          " does not implement the DbTestMonkey.Contracts.IDatabaseProvider<IDbConnection> interface.");
            }

            provider.LogAction = logAction;

            logAction(
                "Provider has been successfully created. Preparing to clear database and run pre-deployment scripts if required.");

            // Clear all the existing data out of the configured databases and re-seed base data.
            ExecuteActionForAllDatabases(sender.GetType(), dbAttributes, provider, dbName => provider.ExecutePreTestTasks(dbName));

            logAction("Databases have successfully been cleared and potentially re-seeded. Connections will now be set up.");

            ProviderConfigurationBase providerConfig =
                (ProviderConfigurationBase)ConfigurationManager.GetSection("dbTestMonkey/" + provider.ConfigurationSectionName);

            if (dbAttributes.Any())
            {
                // Set up connections for database defined in the UsesDatabasesAttribute.
                foreach (var database in dbAttributes.First().Databases)
                {
                    var connectionProperty = FindBestMatchConnectionProperty(sender, database, providerConfig);

                    if (connectionProperty != null)
                    {
                        logAction("Populating connection property " + connectionProperty.Name + " as configured in the UsesDatabaseAttribute.");

                        SetConnectionProperty(sender, activeConnectionProperties, provider, database, connectionProperty);
                    }
                }
            }

            // Set up any remaining connections that have target database names defined in a ConnectionAttribute.
            foreach (var connectionProperty in methodBase.DeclaringType
                     .GetProperties()
                     .Where(pi =>
                            !activeConnectionProperties.Contains(pi) &&
                            pi.CustomAttributes.Any(a => a.AttributeType.Name == "ConnectionAttribute")))
            {
                var connAttribute = connectionProperty.GetCustomAttribute(typeof(ConnectionAttribute), true) as ConnectionAttribute;

                if (connAttribute != null && connAttribute.TargetDatabaseName != null)
                {
                    logAction("Populating connection property " + connectionProperty.Name + " as configured in the ConnectionAttribute.");

                    SetConnectionProperty(
                        sender,
                        activeConnectionProperties,
                        provider,
                        connAttribute.TargetDatabaseName,
                        connectionProperty);
                }
            }

            // Get all the properties that haven't yet been populated and populate them.
            foreach (var prop in methodBase.DeclaringType.GetProperties().Where(p => !activeConnectionProperties.Any(c => c.Name == p.Name)))
            {
                var databases = providerConfig.Databases.Cast <DatabaseConfiguration>();

                if (databases.Any(d => d.ConnectionPropertyName == prop.Name))
                {
                    string databaseName = databases.FirstOrDefault(d => d.ConnectionPropertyName == prop.Name).DatabaseName;

                    if (databaseName != null)
                    {
                        logAction("Populating connection property " + prop.Name + " as configured in app.config.");

                        SetConnectionProperty(sender, activeConnectionProperties, provider, databaseName, prop);
                    }
                }
            }
        }