2017-06-17 103 views
0

以及前指定我的问题,我想告诉大家,我是新来测试领域,所以这里是我的问题:测试涉及数据库

我开发利用快递+ sequelize(MySQL的)一个REST API,我想为我的api写一些测试。我选择使用茉莉花库进行测试。

所以我知道我想测试createupdate其余端点,我需要访问数据库,但问题是测试用例并行运行,并且只有一个数据库,所以如果我想要要从测试用例中的表中删除所有项目,并且另一个测试用例在该表中创建了一行,则会出现问题。

const request = require('superagent'); 

const models = require('../../src/models'); 
const Station = models.Station; 

describe("station testing", function() { 


    before(() => { 
     // delete and recreate all database table 
     // before running any test 
    }); 


    describe("crud station", function() { 
     it('should create model',() => { 

      Station.create({ 
       'name': 'test', 
       lat: 12, 
       long: 123, 
      }).then(model => { 
       expect(model).toBeTruthy(); 
      }); 

     }); 

      it('should delete evrything',() => { 


      Station.deleteAll().then(() => { 

       // problem here if after the first model is created and before create model except is executed 
       expect(Station.Count()).toEqual(0); 
      } 


     }); 

    }); 



}); 
+0

另一个可能对你更好的测试框架是pyresttest。您只需定义您期望的请求和响应,然后就可以检查它。 – HSchmale

+0

@ HSchmale谢谢你的提议,但我想学习如何在通用测试中,所以我需要解决这个问题。 – karim

回答

1

你的问题是你没有在这里编写单元测试。

您需要了解单元测试的最重要的规则 - 唯一的测试一个单位在同一时间。一个单位可以被认为是你的代码的一个区域。在传统的桌面项目(Java,C#等)中,一个单元将是一个类。在Javascript的情况下,一个单元很难定义,但它肯定会只有包含Javacript。如果您在测试中包含任何服务器代码(例如数据库),那么您不是单元测试,而是在进行集成测试(这也非常重要,但要困难得多)。

您的Javascript将具有依赖关系(即它调用的其他代码,通过Ajax调用),在您的情况下将包含被调用的服务器代码。为了进行单元测试,您需要确保您只是测试Javascript,这意味着在运行测试时,您不希望服务器代码被调用。这样,您可以隔离代码单元中的任何错误,并且可以确信发现的任何问题确实在该单元中。如果你包括其他单位,那么它可能是其他单位有问题。

在强类型语言(如Java,C#等)中,有框架允许您为每个依赖项设置模拟。虽然我没有尝试过自己(这是本周的工作),但有mocking frameworks for Javascript,你可能需要使用其中一个来做真正的单元测试。你嘲笑了服务器代码,所以当你运行测试时,它实际上并没有打到数据库。除了解决您的问题外,它还可以避免一些其他问题,您可能会在目前的方法中遇到一些问题。

如果您不想使用模拟框架,另一种方法是更改​​您的Javascript,以便您正在测试的函数带有一个额外的参数,这是一个实际服务器调用的函数。所以,与其...

deleteCustomer(42); 

deleteCustomer(id) { 
    validate(id); 
    $.ajax(...); 
} 

...您的代码应该是这样的......

deleteCustomer(42, callServer); 

deleteCustomer(id, serverCall) { 
    validate(id); 
    serverCall(id); 
} 

...其中serverCall()包含Ajax调用。

然后,进行单元测试,你将测试这样的事情...

deleteCustomer(42, function(){}); 

...,这样,而不是调用服务器,没有什么实际完成的。

这显然需要重写一下你的代码,这可以通过嘲笑来避免,但是会起作用。我的建议是花一些时间学习如何使用模拟框架。它将长期得到回报。

对不起,这已经有点长了。不幸的是,你正在进入一个复杂的单元测试领域,了解你在做什么很重要。我强烈建议你在进一步学习之前阅读单元测试,因为对基础知识的深入理解将在以后为您节省很多麻烦。 Robert Martin(即Bob叔叔)关于此主题的任何内容都会很好,但网络上有大量资源。

希望这会有所帮助。如果您需要更多信息或澄清,请离开。

+0

谢谢你对这个细节的解释:),我只是想知道是否有一个很好的测试教科书。 – karim

+0

@karim周围有很多好书。我不能推荐任何具体的东西,因为我通过阅读Bob博士的文章了解了我的大部分知识,并在其他文章中寻找。关于YouTube上的这个主题有很多视频,所以可能值得关注一些视频。 –

+0

@ karim忘记提及,如果您对任何强类型的面向对象语言感到满意,那么首先应该对其中一个进行TDD研究。您会发现比尝试使用Javascript更容易。 –

1

Jasmine支持beforeEach函数,它在describe块中的每个spec之前运行。 你可以使用它。

describe("A spec using beforeEach and afterEach", function() { 
    var foo = 0; 
    beforeEach(function() { foo += 1; }); 
    afterEach(function() { foo = 0; }); 
    it("is just a function, so it can contain any code", function() { 
    expect(foo).toEqual(1); 
    }); 
    it("can have more than one expectation", function() { 
    expect(foo).toEqual(1) 
    expect(true).toEqual(true); 
    }); 
}); 

因此,你可以让beforeEach照顾删除操作。