search

Home  >  Q&A  >  body text

node.js - 最佳实践:使用NodeJS进行web开发,如何优雅地进行数据层的单元测试?

仔细想了下,觉得我问的这个问题维度可大可小,我就列一下我的一些困扰吧,求给建议或者分享经验。

如何确定测试的维度?

以一个常见的web应用为例,我们一般会有数据层(完全对数据库的操作封装),面向客户端的业务接口,可能还会有面向第三方应用的API。那么如此一般你们会对那些维度进行测试呢?比如:

纠结主要在于虽然是不同层的测试,但是其实有非常多得荣誉在里面。比如数据层的一个createUser 方法的测试,对于API的HTTP层,无非可能直接就是把用户输入传到这个方法里面,然后返回这个方法的结果给客户端。

测试的具体编写你们一般怎么搞?

目前来说这些测试我都是手写,不知道大家是否有更加自动化的方式做这些测试。手写的话,我个人感觉问题有:

jsdescribe( 'common', function(){
    it( '添加用户', function( done ){
        done();
    });

    it( '获取用户列表', function( done ){
        done();
    });

    it( '获取某个用户', function( done ){
        done();
    });

    it( '更新用户', function( done ){
        done();
    });

    it( '删除用户', function( done ){
        done();
    });
});

感觉应该是比较常见的case,那么除了第一个“添加用户”外,可以看到,其他得所有case都需要“某个用户已经被添加”为前提。那么一般大家是怎么操作呢?我想到的思路有两种:


欢迎发散分享经验!!!!

PHP中文网PHP中文网2769 days ago371

reply all(3)I'll reply

  • 巴扎黑

    巴扎黑2017-04-17 11:35:36

    According to my experience:

    • Testing should be based on "business process" rather than "interface"
    • Do not share data between different tests, and do not use global variables if possible
    • Write business logic in the Model as much as possible (or abstract a Service layer separately), do not write it in the Controller
    • If you find that there are many duplicate tests, you can not write a test (or only write a test for one of the places), wait until you find a problem with a certain function, and then write a test for the problem

    The so-called "business process" refers to a process similar to "an ordinary user registers an account, logs in, changes the password, posts, and replies" or "an administrator account logs in to the administrator panel, posts, replies, and deletes other people's posts." This has many benefits. For example, each test in the first process shares the same "normal user", and the second process all shares an "administrator user".

    Sharing data within a process is more controllable, because a process is generally not too long, and the internal connections are relatively large. If you test each interface, you must either prepare data for each test separately (very cumbersome), or share data between all tests (there will be many global variables, which will greatly increase the complexity, and the tests will interact with each other). Interference may also occur).

    You should ensure that the tests in each test file are independent. Use before to define the data that this file depends on (for example, all tests in this file need to have a user first). You can define a <🎜 in other files. > Function that accepts some options and then generates test data that meets the requirements. The advantage of this is that you can run a certain test separately. If running the entire test is time-consuming, this can save a lot of time, and you don't have to worry about the tests interfering with each other. Moreover, libraries such as mocha do not guarantee the running order between different test files (although they will actually run in alphabetical order). If there are dependencies between different test files, it will be very troublesome. createTestAccount

    As for whether to test the API interface or the Model, this is a matter of opinion, but the point of "try to write business logic into the Model" will not change.

    If you are testing the API, then the test can directly call the methods in the Model to prepare data and verify the test results (it is much more convenient than using the API to prepare data and verify the results); if you are testing the Model, because Most of the logic is in the Model, so after testing the Model, you can basically guarantee that there will be no major problems, because there is not much logic in the Controller.

    Finally, please do not use the "code generator" to generate test code. Being able to generate it with a script shows that there is an inherent logic between these tests. You can completely avoid duplicate code through good design. After all, mocha's tests are all JavaScript code. What can't be achieved? Of course, the level of abstraction of the test cannot be too high and should be a little more straightforward. Otherwise, too much time will be spent on "debugging and testing". You need to make a trade-off between this.

    For information on "Code Generator", please refer to the "Evil Guide" section of the book "The Way of Programmers: From Jobber to Expert". This book also introduces a large number of techniques for writing automatic tests.

    reply
    0
  • 阿神

    阿神2017-04-17 11:35:36

    This is how I do API testing. There is no way. It must be done
    If your ORM or similar data engine is developed by yourself, just ensure that this is no problem
    For complex data operations, do some unit tests. If it is just a very simple function, it is not necessary
    Of course, except for TDD, for entrepreneurial teams, it is difficult to test comprehensively, just master a certain degree~

    reply
    0
  • PHP中文网

    PHP中文网2017-04-17 11:35:36

    My understanding is: test what remains unchanged
    For example, if you test an API, the application public interface (short for API) will remain unchanged. Because you have made it public, others are using it. If you change the interface and others call it for your API, will it be OK? Report an error?
    In fact, unit testing also tests this [object or element or entry] interface. No one will test private method or protected method
    The same is true for testing business logic. Why? Normally, the product is not in the release development stage, and the business logic should be stable. Otherwise, how do you do it? Things are not finished yet, and the requirements have changed

    Practice: Find out the business logic to test. If your business logic is written in the model, then test the model. If it is written in the service, you will test the service.
    Usually an API should correspond to a business logic. Once you test the business logic, you naturally don’t need to test the API. For example
    user->getuser() This method will correspond to an api of http://domain.com/getuser.xxxx
    This is also the origin of RESTful. My understanding is that a method in ror will be automatically mapped to a webservice or api, allowing people to call it

    Finally, let me emphasize: Don’t be so dogmatic. All testing should be based on this principle [test whatever doesn’t change]. If something keeps changing, how do you test it?

    reply
    0
  • Cancelreply