2013-10-15 57 views
2

我们的解决方案有两个不同的数据库提供者,它们都位于不同的项目中。他们都继承了位于我们核心项目中的共同IDbProvider如何针对两个不同的数据库运行我的集成测试?

namespace OurApp.Data 
{ 
    public interface IDbProvider 
    { 
     // truncated 
    } 
} 
namespace OurApp.Data.SqlServer 
{ 
    public class DbProvider : IDbProvider {} 
} 
namespace OurApp.Data.Sqlite 
{ 
    public class DbProvider : IDbProvider {} 
} 

的数据库必须在功能上是相同的,而且我们已经有了集成测试对SqlServer.DbProvider工作。

当前,所有RepositoryTests都从基类继承。

public abstract class RepositoryTestsBase 
{ 
    protected IDbConnectionProvider Connection; 
    protected IDbProvider DbProvider; 

    [SetUp] 
    public void Setup() 
    { 
     // Need to create a new connection to the server and make sure there is no database 
     ConnectionStringSettings dbConnection = ConfigurationManager.ConnectionStrings["databaseConnection"]; 
     string testDatabaseName = ConfigurationManager.AppSettings["databaseName"]; 

     Connection = new DbConnectionProvider(dbConnection.ConnectionString, dbConnection.ProviderName); 
     DbProvider = new DbProvider(Connection, testDatabaseName); 
    } 

我真的讨厌不得不CTRL +ç/CTRL +V我所有的集成测试只改变DbProvider。

是否有一种方法可以运行所有集成测试两次,而只需为每次运行注入不同的DbProvider?我希望能够(显然)在Powershell构建中执行此操作,但也可以在IDE中执行此操作。

我最初的想法是创建两个公有方法和一个私有方法,注入适当的数据库提供程序。

[Test] 
public void ShouldDoStuff_SQLServer() { 
    var dbProvider = sqlserver.DbProvider; 
    ShouldDoStuff(dbprovider); 
} 

[Test] 
public void ShouldDoStuff_Sqlite() { 
    var dbProvider = sqlite.DbProvider; 
    ShouldDoStuff(dbprovider); 
} 

private void ShouldDoStuff (IDbProvider dbprovider){ 
    // Assert 
} 
+0

哪个测试框架,您使用的? –

+0

我已更新我的问题。我们正在使用nunit。 –

+0

有多种方式。但是如果不知道某些细节(测试框架,现有代码等),就不可能提出具体的方法。 –

回答

3

一个解决方案可能是使用参数化测试。这个想法是,你的测试有不同的数据传递给它每次运行,从而允许你运行两次测试,一次针对每个数据库。

看看http://www.nunit.org/index.php?p=testCaseSource&r=2.6.2,看看它是否会满足您的需求。

你的情况,你可能会碰到这样的:

static IDbProvider[] DbProviders = new IDbProvider[] 
{ 
    sqlserver.DbProvider, 
    sqlite.DbProvider 
}; 

[Test, TestCaseSource("DbProviders")] 
public void TestMethod(IDbProvider dbProvider) 
{ 
    ShouldDoStuff(dbprovider); 
} 

另外,运行在对两家供应商的类中的所有测试,尝试这样的事情:

[TestFixture(0)] 
[TestFixture(1)] 
public class RepositoryTests 
{ 
    private IDbProvider _provider; 

    public IDbProvider(int index) 
    { 
     _provider = IDbProvider[index]; 
    } 


    static IDbProvider[] DbProviders = new IDbProvider[] 
    { 
     sqlserver.DbProvider, 
     sqlite.DbProvider 
    }; 

    [Test] 
    public void TestMethod(IDbProvider dbProvider) 
    { 
     ShouldDoStuff(_provider); 
    } 
} 
+0

这看起来很有前途。我已更新我的问题以获取更多详细信息。有没有可能只参数化'SetUp'?让它们运行两次看起来会是什么样子? –

+0

在'TestMethod'中,我只是'foreach(var dbp in dbProvider)ShouldDoStuff(dbprovider)'?或者TestCaseSource知道调用它两次? –

+1

不需要一个foreach。 NUnit将运行您的测试方法两次,每次为DbProviders中的每个值运行一次。 –

2

你可以使用数据组合驱动的测试用一个值源沿着这些路线:

public IEnumerable Providers() 
{ 
    yield return new OurApp.Data.SqlServer.DbProvider(); 
    yield return new OurApp.Data.Sqlite.DbProvider(); 
} 

[Test] 
public void MyTest([ValueSource("Providers")] IDbProvider provider) 
{ 
    // Test code... 
} 

Ť他的测试方法会为您从价值源返回的每个对象调用一次。

查看NUnit文档here 当然,您还需要在测试项目的配置文件中提供db config的东西。

HTH 托马斯

+0

我们的数据库配置的东西目前正在安装程序中发生。你是否说需要移动到配置文件? –

+0

不一定。您只需确保从值源返回的提供程序正确初始化即可。你甚至可以直接在'提供者'枚举器中做到这一点...... –

+0

好吧,所以现在这两个答案都非常有意义,但是有没有办法在SetUp上而不是在每个单独的测试中做到这一点? –

0

你可以沿着这些线路做到这一点:

[TestFixture] 
public class RepositoryTests 
{ 
    protected IDbConnectionProvider Connection_SQLServer; 
    protected IDbConnectionProvider Connection_SQLLite; 
    protected string testDatabaseName_SQLServer; 
    protected string testDatabaseName_SQLLite; 

    [SetUp] 
    public void Setup() 
    { 
     // init both providers and db-names 
    } 

    public IEnumerable Providers() 
    { 
     yield return new SqlServer.DbProvider(testDatabaseName_SQLServer, Connection_SQLServer); 
     yield return new Sqlite.DbProvider(testDatabaseName_SQLLite, Connection_SQLLite); 
    } 

    // Do tests 
相关问题