Why should Mocha test cases be stateless?

筅森魡賤 提交于 2019-12-30 11:53:10

问题


It is a common recommendation, that Mocha test cases should not share state. In light of Mochas strongly sequential nature of execution of test cases, I really do not understand this recommentation. And more - I see it dubious.

If the test cases, even asynchronic ones, are executed strictly one after another, there is no risk of time-race problems or other unpredicted execution sequence.

Let's take this Mocha structure:

describe
   describe
     it1
     it2    // async
     it3
   describe
     it4
     it5
describe
   describe
     it6    // async
     it7    // async
     it8
   describe
     it9
     it10

Test cases will ALWAYS be executed in clear sequential order, it1, it2,... it10, independently on whether they are sync or async, independently even on hierarchy of describes. The following structure will produce perfectly the same output:

describe
   it1
   it2    // async
   it3
   it4
   it5
   it6    // async
   it7    // async
   it8
   it9
   it10

Shared data between test cases in a single describe() can make it much easier and comfortable to communicate between test cases in order to:

  • reuse testing code and avoid repeating the same logic in each (or some of them) test case. Hooks can be handy here, but sometimes is more control expected than they offer
  • to reduce the testing execution time - a lots of time can be saved avoiding too many hooks that do nothing but satisfying this recommendation about statelessness.

Another fact in favor of using shared data between test cases is this simple and nice structure of the Mocha code. Different level of describe()s permit an easy and clear scope management for this eventual shared data.

The only negative side I see is making the code harder to understand, follow and maintain, when the "globals" are being "abused". Anyhow, nothing that cannot be avoided by disciplined coding.

Is there something I'm not aware of here?


回答1:


It is possible to use Mocha to run tests that are not stateless and thus depend on one another. It's just not what Mocha was designed for. At the end of the day, if you want to impose dependencies between your tests, well, sure, you can. It comes with some caveats though.

Optimizing for the Wrong Thing

You cite this advantage to sharing state among tests:

to reduce the testing execution time

Sure. All else being equal, we'd rather have a test suite that takes less time to run. Not resetting state between tests could amount to quite a bit of time saved on large test suites when running the entire suite. However, the fact is that "all else" is not equal:

  • Running an entire suite should be done by an automated process that reports what passed and what failed. In other words, there should be no one sitting there waiting for the whole suite to complete.

  • When there is a failure or when a new test is being implemented, the developer will want to run only that test which fails or the new test, not the whole suite. If the suite is designed so that tests 1 to N-1 must be run before test N is run, then this is that much more time the developer is waiting to get the result of the test he actually cares about. So he can sit there and twiddle his thumbs at a rate of $X/minute. "Multitask" is not the answer, as it has been proved that there is a cognitive cost to switching tasks. ("Ok the test is done... wait, what was the issue again?")

Test Selection

You can use --grep to select specific tests. This is extremely useful on large test suites to avoid wasting time to run tests you do not care about. So let's suppose that the titles of your tests are it1, ... it10 and you use --grep it7. Since Mocha takes all the tests to be independent from one another, it will just run whatever before and beforeEach hooks are applicable to it7 and run the test (and then run whatever after and afterEach hooks apply to it). It won't run it1 to it6 before running it7. For it to run these tests, you'd have to craft a --grep that covers all the necessary tests, which is certainly always possible to do but not pleasant.

In the HTML interface that you get when running Mocha in a browser, you can click on a test if you want Mocha to just run that test. Again, this is extremely useful if you have a single failing test that you want to fix. There's simply no equivalent to this simple click if it happens that the failing test is dependent on a bunch of tests that should run before it.

Test Order

In general, if your tests must run in a specific order, you have to be careful to ensure that tests split among multiple files are going to load in the order necessary for your tests to run.

For instance, it would be possible to share state among tests stored in different files using a global structure. However, when tests are in different files (where one file does not require the other), the order in which the files are processed by Mocha is completely dependent on the order in which the filesystem lists the files when the directory that contains them is read. There is a --sort option for those who want a predictable order based on a lexicographic sort. If you want to impose your own arbitrary order, then I guess you'll have to name your files 01foo.js, 02bar.js, etc.

This is true whether using Node.js to run Mocha or running Mocha in a browser. I have suites where the test files are loaded with RequireJS. Requesting modules A, B, C won't guaranteed that they'll be loaded in the order A, B, C unless C is declared to depend on B (and maybe A) and B to depend on A.



来源:https://stackoverflow.com/questions/29508444/why-should-mocha-test-cases-be-stateless

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!