Skip to content
This repository

Support for beforeAll and afterAll #56

Closed
wants to merge 1 commit into from
Jacob

This adds support for beforeAll and afterAll... something i'd really like to see (and something @jasminebdd said you were interested in)

Gregory Moeck

I know not having a beforeAll and afterAll encourages good habits for unit tests, but it would be quite helpful to have for integration/functional tests. +1

Jacob

hm... out of curiosity, how does not having a beforeAll/afterAll encourage good habits?

Gregory Moeck

I think it was Roy Osherove in his book "The Art Of Unit Testing" who called using beforeAll/afterAll in a unit test a test smell. Basically his point was if your doing setup and teardown in a unit test, your not isolating a single unit, but doing an integration/functional test across multiple units.

Jacob
fat commented April 10, 2011

next time i see pivot andrew or pivot Jonathan i'm going to have them attack you for not looking at either of my pull requests O_O

Davis W. Frank
Owner

Point taken.

Do you want a true beforeAll that runs once? Or are you looking for a top-level beforeEach?

We're not fans of the former as it almost always drives you nuts chasing down what you thought was test pollution.

As for the latter, a beforeEach or afterEach placed in global scope does this.

Knowing this, what's your take on this pull request?

Jacob
fat commented April 17, 2011

Hm... my take is that you wont' be pulling this.

Jacob fat closed this April 17, 2011
Jacob
fat commented April 17, 2011

I'm sad that you tricked me though: http://cl.ly/64PF

Jacob fat reopened this April 17, 2011
Jacob
fat commented April 17, 2011

feel free to close after viewing your trickery.

James Baker

I'm surprised that this doesn't exist ('this' being "suite-level before and after"). A) Why wouldn't you allow functional tests? Is Jasmine really designed to prohibit other types of tests? or B) Even for unit tests, it's sometimes silly to insist that each each test set up and tear down its entire environment.

You can argue that question B is really just question A reframed, but... what's the benefit to trying to be more ideologically pure than RSpec?

Lars-Erik Roald
lroal commented July 01, 2011

I really think that BeforeAll is the de-facto way og doing BDD style in unit tests. It is pathetic that jasmine doesn't support it. The BeforeAll should contain the arrange and act. The tests should only contain simple assert ( no acting!!) to verify state after the Act. If you have any kind of acting in the test methods - it is not BDD.

garren smith

I would really like to see this functionality added, its in RSpec and is really useful. Nothing wrong with using for functional testing

Arian Stolwijk
arian commented July 01, 2011

:+1:

Justin Searls
searls commented July 02, 2011

There definitely isn't currently a way to do beforeAll/afterAll cleanly. When I have some setup code that needs to run exactly once for my tests, I generally do so at the very top-level in an anonymous function. I presume a beforeAll would run exactly one time for all the specs & example groups beneath it.

That said, I'd love if someone could gist up a practical example of a clean spec that really needs this feature. One year and ~3000 Jasmine specs later and I don't think this topic has ever crossed my mind.

To @lroal's point--do you know about beforeEach? I do my arrange & act in a beforeEach and keep every it to a single line.

Lars-Erik Roald
lroal commented July 03, 2011

I agree that doing all the setup in a top-level anonymous function will do just fine - and make the BeforeAll() redundant. Still, there is no way to do AfterAll().

@searl, a practical example where AfterAll is needed: let´s say we do a database test, perhaps with lazy loading of properties. In the AfterAll function we need to close the database connection/transaction. The BeforeAll would typical be: "When Getting A Customer From The Database". The "its" would be it("should set correct CustomerId") and it("should set correct name") .
The BeforeAll act would be composed by two steps 1) Arrange: put the fake customer data into the db 2) Act: retrieve customer from db. The AfterAll: delete the fakedata in the db, close the db connection.
(Usually, the arrange part would also contain the cleanup step to delete fake data from previous tests if the tests throw exception before reaching the AfterAll)

Yes, I do know about beforeEach. Ideally, I think the BeforeEach and AfterEach shouldn´t exist in a BDD testing framework in the first place. Because it encourages non-BDD style. After all, isn´t jasmine supposed to by BDD styled ?

Jacob
fat commented July 03, 2011

+1 to @lroal

This is made really easy with other bdd style frameworks like vows...

Set up a topic, then have several logic-less asserts executing against the topic.

doing all the setup in a top-level anonymous function will do just fine

It will work... but it's a hack and makes your spec look ugly. It also isn't really explicit what's going on to someone who isn't familiar with jasmine.

Fabio M. Costa

+1! what are we waiting for? :S

Lars-Erik Roald
lroal commented July 04, 2011

+1 @fat yes, an explicit BeforeAll() method is cleaner.

Adam McDonald
raid5 commented July 14, 2011

+1 This would be really useful to cleaning my test db before/after all specs are run.

Deleted user
ghost commented July 26, 2011

The content you are editing has changed. Reload the page and try again.

+1000. Here is a good example of having this support.

I'm testing search functionalities (full text search) and have to upload approximately 1 000 documents into a database.

I have a lot of tests and right now I have to upload them and then there it down for all tests and that takes a lot of time.

It would be better to allow me to upload them once.

The tests are isolated since each test won't change anything but just doing a search.

So please merge this pull request.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Esa-Matti Suuronen

+1

One can do simple synchronous stuff without this, but for async setups this is really required.

Edit: Does this patch support async operations? If not, it should like the beforeEach supports with asyncSpecWait.

Tim Oxley

+1

JP Richardson

I would also like to see this....

Jan Mühlemann

+1

Gian Marco Gherardi

+1

Tim Oxley

Hey @pivotal, what's your status on this?

Daniel Stocks

Jumping the bandwagon

+1

Although a possible workaround (for now) is just to run your functions outside the describe block and access the results stored in a variable.

Or am I doing something wrong? ><

Arian Stolwijk

Other workaround:

describe('foo', function(){

    var _beforeAll = false;
    beforeEach(function(){
        if (_beforeAll) return;
        _beforeAll = true;
        // do your thing
    });

    it('should test things', function(){

    });

});
Paul Covell

I am looking for a way to do this to integrate my Javascript tests with Browserify -- I need to start a copy of the server and pull down the server Javascript bundle, and it doesn't make sense to do this more than once. Also, I want to do this across every test in the suite, so I don't see a way to do it outside of a beforeAll/afterAll. I can prevent the server from running more than once, but I also need to shut it down when the tests are complete, and I don't see how to do that.

I see a workaround: I can start it and have every suite increment a counter in their local beforeEach and decrement in their afterEach. Yuck.

Deleted user

The content you are editing has changed. Reload the page and try again.

It has gone 9 months without a close or merge.

At least comment on what you are planning to do.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Paul Miller

@pivotal ping ping ping ping ping.

Deleted user

The content you are editing has changed. Reload the page and try again.

For all node.js users there is now: http://visionmedia.github.com/mocha/

It supports before() and after()

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Paul Miller

@johnnywengluu thanks for info, mocha seems to be better than jasmine. And it supports node.js out-of-box.

Deleted user

The content you are editing has changed. Reload the page and try again.

@paulmillr: It's written by the author of express, jade and stylus so it's rock solid.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Tim Oxley

+1 for mocha. DOWN WITH PIVOTAL :D

Augusto Becciu

+1

Jacob fat closed this December 04, 2011
Jacob

sorry, everyone, i'm deleting my fork of jasmine. I don't want anything to do with this project.

Rajan Agaskar
Collaborator

Apologies to fat and everyone else invested in the outcome of this thread for the lack of motion/feedback on this pull request -- most of our Jasmine efforts have been focused on making sure we work with Rails 3.1.

I don't think anyone should plan on seeing this in Jasmine any time soon, although I think we'd like to make it possible for end-users to change how Jasmine works (either via callback hooks or add-ons).

The big obstacle here is adding a beforeAll to the public interface, a feature which none of the maintainers really want to encourage or support.

Lars-Erik Roald

So Jasmine is integrated with the bloated Rails framework - that makes it final to me - Goodbye Jasmine. No more Jasmine , ever.

JP Richardson

@Iroal... I didn't infer that to mean that it's integrated with Rails, but rather it's just made to work with Rails. Regardless, fortunately Mocha is a suitable alternative.

Alexey Petrushin

The same, switching to mocha.

Christopher Sansone

I'm late to the party here, but I have the same issue in some of my specs where the setup and teardown is too expensive to execute each time. I (as well as everyone here with this issue) am smart enough to know when it makes sense to execute beforeEach vs beforeAll. If I use it incorrectly and wind up with broken specs, I have nobody to blame but myself. I would consider beforeAll / afterAll to be another tool in the toolbox to use where appropriate.

That said, here is a workaround that has suited us well. Just include these definitions in a helper file somewhere:

var beforeAll = function(fn) {
  it('[beforeAll]', fn)
}

var afterAll = function(fn) {
  it('[afterAll]', fn)
}

It is obviously a little silly, but it gets the job done for us. Just be sure the beforeAll() is at the top of your describe block, and the afterAll() is at the bottom of your describe block. If you have issues involving the order of execution between the all() and each() helpers, you should be able to resolve them using a nested describe block.

To the maintainers of jasmine: thank you for an exceptional tool. Don't let the haters get you down. Obviously you can decide what jasmine is and is not, but I still highly encourage you to implement this functionality. It is clear that a lot of people need it, and please do not infer that your user base is not smart enough to use it properly. Yes, it can cause "test smells" and it should be used with caution, but when you need it, you need it.

Davis W. Frank
Owner

Thanks Christopher.

Your solution is a perfectly fine way to implement before/afterAll and doesn't add to the complexity of Jasmine core.

Doug McInnes

I'm also late to the party but I also gotta say +1 on this, there are legitimate cases where beforeAll is useful.
Christopher's solution is not ideal, it inflates the spec readout.
My problem is that I'm testing library files that I only want to load once per top level suite. I don't want them to all load at the beginning because I reset DOM and global state before every suite is loaded because I don't want stubs and other library modification to bleed into other specs (some libraries are shared between specs).

FWIW here's my MonkeyPatch -- just drop it in your global scope:

var beforeAll = function (func) {
  var beforeAllCalled = false;

  jasmine.getEnv().currentSuite.beforeEach(function () {
    if (!beforeAllCalled) {
      beforeAllCalled = true;
      func();
    }
  });
};
Tim Oxley

Whoaa, hang on with all that code there @dmcinnes! If a recognised leader in agile like Pivotal Labs doesn't want to take on supporting the complexity of those 9 lines of code, then why do you expect other people to? This is appalling. Do you even know what kind of work is involved @dmcinnes? Are you even agile, at all @dmcinnes???

Mario Izquierdo

I didn't see in any of the comments of this thread where beforeAll would be more useful:

describe('foo', function () {
  beforeAll(function () {
   // Executed only once, before all examples
  );

  beforeEach(function () {
    // Executed 4 times, once before each example
  });

  it("should foo", function () { /* test stuff */ });
  it("should foo revenge", function () { /* test stuff */ });

  describe('nested foo', function () {
      beforeAll(function () {
        // Executed only once, before all *nested* examples
      );

      beforeEach(function () {
        // Executed 2 times, once before each nested example
      });

      it("should complain...", function () { /* test stuff */ });
      it("Y U NO HAZ BEFOREALL", function () { /* test stuff */ });
  });
});

This is the same behavior as in RSpec and it allows for very flexible setup and performance

Wojciech Zawistowski

My use case for this is testing with mongoDB (under jasmine-node).

Currently Jasmine works in such way, that mongo connection hangs and test results never gets displayed. The solution for this is to manually close connection, but it is overkill to open and close connection in beforeEach / afterEach. Collection should be emptied on beforeEach, but connection should be established and then closed only once for the whole suite, in beforeAll / afterAll.

I think this is an example of very legitimate case for having afterAll clean-up method.

Martin Häcker

+1

Michael Wynholds

I needed an afterAll() for the same Mongo open connection issue as velesin and dwt. I hacked together a solution. First, all of my test files require a 'test_support.coffee' file. Then I put code similar to this in there:

timeout = null

afterAll = ->
  # do whatever you want here! it only runs once at the end.

beforeEach ->
  clearTimeout timeout if timeout?

afterEach ->
  timeout = setTimeout afterAll, 100

The beforeEach() and afterEach() handle the timing for calling afterAll(). Obviously you can put anything you want in the afterAll().

In my case, I had to close the mongodb connection (db.close()), and I also had to stop one or more express servers that had been started by supertest. And then, boom!, the test execution stops without passing --forceexit to jasmine-node.

Roberto Huelga

+1 for beforeAll / afterAll, I love jasmine but really thinking to switch mocha for this.

beforeAll could be also useful for asynchronous:

describe("async"
    beforeAll
        runs( ...
        waitsFor( ...

    it( 'first '
        runs(
            expects ...
    it( 'second'
        runs(
            expects ...
    it( 'third'
        runs(
            expects ...

Using beforeEach here can increase a lot the execution time.

The whole handling of this pull request on the part of the Jasmine team makes me less confident about the quality of this tool, given the huge amount of requests from the community which where ignored.

Aaron Eischeid

+1 for adding this tool to Jasmine.

In my personal use case I think beforeAll would be merely a optionally nice way of organizing the test code, the functionality I really need is in the .afterAll()

I hope you are still open to reconsidering

Tyler Cloke

1+ would really be useful...

Giovanni Bassi

I have put together some ideas, this is what I came up with:
https://github.com/giggio/open-store/blob/3bf0d3487ce4c92317fa3f9240ab042414090839/src/spec/support/global.coffee
It is still in the begining, but it is working.
Basically:

exports.beforeAll = (func) =>
  @beforeAllFunc = func

exports.afterAll = (func) =>
  @afterAllFunc = func

exports._setupAfterAll = ->
  runner = jasmine.getEnv().currentRunner()
  oldFinishCallback = runner.finishCallback
  self = @
  runner.finishCallback = ->
    oldFinishCallback.apply @, arguments
    self.afterAllFunc() if self.afterAllFunc

beforeEach =>
  return if @beforeAllCalled
  @beforeAllCalled = true
  exports._setupAfterAll()
  @beforeAllFunc() if @beforeAllFunc
Dan Kohn

Just a note that that BeforeAll is really unnecessary, since any items can be synchronously requireed at the top of a file. However, there is not substitute for AfterAll to have the ability to stop a server when doing integration or acceptance testing (in jasmine-node). Adding a timeout before closing the server is a ludicrous hack compared to just being given a notification that all tests have completed. Therefore, like many others, I'm giving up on Jasmine and switching to Mocha.

Dan Kohn dankohn referenced this pull request in visionmedia/mocha April 08, 2013
Closed

Can mocha output the number of assertions? #800

tdumitrescu referenced this pull request in mhevery/jasmine-node November 20, 2013
Open

No way to run code after all tests complete #241

Boris Serdyuk

+1. I have setup code before all tests and teardown at end. I want to use Mockery with jasmine, and I have to enable/disable mocking before every test, instead of do it one time.

WhatFreshHellIsThis

Someone with limited imagination or being willfully ignorant asked why anyone would need a before all: I wanted this because the Angular.js newest method of E2E testing (Protractor) uses Jasmine by default, however I need to trigger a complete reset of my database before I run my suite of Angular tests. Kind of an extremely common requirement for testing anything of modern substance.

After reading the comments here I'm guessing that Jasmine was intended for strictly browser testing and the developers are sticking their heads in the sand and covering their ears and humming to themselves so they can not hear one word about all the other, modern uses for their code (which is fully their right but it's coming across as a little childish and defensive rather than accommodating and open minded).

I'm off to figure out how to use Mocha instead of Jasmine with Protractor.

Andrew Yurisich

@WhatFreshHellIsThis I gave up on it and just used this:

describe('Something', function () {

    it('beforeAll', function () {
        // Don't assert anything
        setupDatabase();
    });

    it('should test stuff', function () {
        // ...
    });

    it('afterAll', function () {
        // Don't assert anything
        teardownDatabase();
    });

});
Arve Knudsen

+1. It's not uncommon to need to share a fixture between a suite of tests.

gburghardt

I'd like to see this added as well. I'm trying to do testing in a browser environment and I am mocking AJAX calls. I really need a "beforeAll" and "afterAll" for a describe block to do all the AJAX call mocking. I really don't see this as functional testing here, because I am isolating one component -- one method in a class, actually.

This whole thread of comments on a highly requested feature is the reason I try not to adhere too strictly to ideologies. Every list of rules I make for programming has this rule at the end:

There is an exception to every rule

I think to most people, Jasmine is a general purpose testing framework first and foremost. We don't look at its utility just through the eyes of one ideology.

I'm also very seriously considering switching to Mocha.

Stepan Riha

FYI, the nonplus/jasmine-beforeAll library adds before/afterAll support to Jasmine (1.3.1).

Ferdinand Prantl

This is all about asynchronous tests, where the JavaScript code flow cannot be used to naturally place the setUp and tearDown sections. When a temporary resource needs to be created before the first test starts and destroyed after the last one finishes, an afterAll cannot be simply worked around, There can be scenario-dependent workarounds like artificial test steps, nesting of describes, hooking into the Runner etc. but it makes understanding the test code more difficult. There should be a single way to do this and the framework should offer it. The beforeAll + afterAll plugin by nonplus (right above) is a great solution.

Paul Miller paulmillr referenced this pull request in chaplinjs/chaplin January 29, 2014
Closed

Switch from Jasmine to Mocha + Chai #117

Antwan Wimberly

This is ridiculous!! Guess I will have to join the mocha bandwagon as well.

Antwan Wimberly armw4 referenced this pull request from a commit in armw4/auth-demo February 27, 2014
Antwan Wimberly Commit latest snapshot.
I've determined why the process blocks after all tests completes. It's
because you have to disconnect from mongodb, or the event loop with be
blocked. This makes sense, but what doesn't is why jasmine doesn't
provide hooks for beforeAll and afterAll. It's here where you'd want to
connect and disconnect from mongodb. Next step is to install the plugin
that monkey patches jasmine to provide this functionality.

* mhevery/jasmine-node#241
* https://github.com/nonplus/jasmine-beforeAll
* pivotal/jasmine#56
0e95b4d
Jeremy

To anyone considering "jumping on the bandwagon", let me just say that I switched to Mocha from Jasmine over a year ago precisely because of this ticket, and I have no regrets. I don't think I expect that much from library authors, but even so I am shocked that a library as popular as Jasmine could be this rude and non-responsive towards its user-base (and for so long!).

At this point I think all anyone can do is vote with their feet. On the plus side, at least there's a superior alternative to switch to, and because Mocha offers a BDD format switching your code over is (mostly) painless. And then once you make the switch everything just works.

Kazark

+1. This feature is useful in the case that after you mutate state in one way, you have multiple asserts that you want to run against that one state change, and you want to spell each one out cleanly:

describe('MyAngularController', function() {
    describe('loadSuccess', function() {
        beforeAll(function() {
            controller.loadSuccess(...);
            ...
        });
        it('sets the number of items', function() {
            expect(...).toBe(6);
        });
        it('places the loaded items in scope', function() {
            expect(...).toEqual(...);
        });
        ...
    });
});

@gmoeck I fail to see how this is a smell for cases like the code above. Roy Osherove's book is good, but he is speaking of xUnit style unit testing, not Spec style. The nesting ability here is arguably more powerful and means that beforeAll does not have to be a smell.

Daniel Tabuenca

To me in BDD-style testing the real smell is doing anything other than logic-less asserts in your "it" blocks.

Starting with a given state, performing a single action that mutates it to a new state, and then performing several read-only assertions that specify the resulting state is a very desirable pattern when doing BDD-style tests.

Kazark

@dtabuenc Well said. I like it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Feb 09, 2011
fat-bot + adds support for beforeAll afterAll 788c701
This page is out of date. Refresh to see the latest.
90  spec/suites/RunnerSpec.js
@@ -13,6 +13,94 @@ describe('RunnerTest', function() {
13 13
     env.clearInterval = fakeTimer.clearInterval;
14 14
   });
15 15
 
  16
+  describe('beforeAll', function(){
  17
+    it('should run before all specs for a given suite', function(){
  18
+      var foo = -1;
  19
+      var bar = function(){
  20
+        foo++;
  21
+      };
  22
+      var spy1 = jasmine.createSpy().andCallFake(bar);
  23
+      var spy2 = jasmine.createSpy().andCallFake(bar);
  24
+      var spy3 = jasmine.createSpy().andCallFake(bar);
  25
+
  26
+      env.beforeAll(spy1);
  27
+
  28
+      env.describe('suite 1', function () {
  29
+        env.it('test 1-1', function() {
  30
+          foo++;
  31
+          this.expect(foo).toEqual(2);
  32
+        });
  33
+        env.it('test 1-2', function() {
  34
+          foo++;
  35
+          this.expect(foo).toEqual(3);
  36
+        });
  37
+        env.beforeAll(spy2);
  38
+      });
  39
+
  40
+      env.describe('suite 2', function () {
  41
+        env.beforeAll(spy3);
  42
+        env.it('test 2-1', function() {
  43
+          foo++;
  44
+          this.expect(foo).toEqual(5);
  45
+        });
  46
+      });
  47
+
  48
+      env.currentRunner().execute();
  49
+
  50
+      var runnerResults = env.currentRunner().results();
  51
+      expect(runnerResults.totalCount).toEqual(3);
  52
+      expect(runnerResults.passedCount).toEqual(3);
  53
+
  54
+      expect(spy1.callCount).toEqual(1);
  55
+      expect(spy2.callCount).toEqual(1);
  56
+      expect(spy3.callCount).toEqual(1);
  57
+    });
  58
+  });
  59
+
  60
+  describe('afterAll', function(){
  61
+    it('should run after all specs for a given suite', function(){
  62
+      var foo = -1;
  63
+      var bar = function(){
  64
+        foo++;
  65
+      };
  66
+      var spy1 = jasmine.createSpy().andCallFake(bar);
  67
+      var spy2 = jasmine.createSpy().andCallFake(bar);
  68
+      var spy3 = jasmine.createSpy().andCallFake(bar);
  69
+
  70
+      env.afterAll(spy1);
  71
+
  72
+      env.describe('suite 1', function () {
  73
+        env.it('test 1-1', function() {
  74
+          foo++;
  75
+          this.expect(foo).toEqual(0);
  76
+        });
  77
+        env.it('test 1-2', function() {
  78
+          foo++;
  79
+          this.expect(foo).toEqual(1);
  80
+        });
  81
+        env.afterAll(spy2);
  82
+      });
  83
+
  84
+      env.describe('suite 2', function () {
  85
+        env.afterAll(spy3);
  86
+        env.it('test 2-1', function() {
  87
+          foo++;
  88
+          this.expect(foo).toEqual(3);
  89
+        });
  90
+      });
  91
+
  92
+      env.currentRunner().execute();
  93
+
  94
+      var runnerResults = env.currentRunner().results();
  95
+      expect(runnerResults.totalCount).toEqual(3);
  96
+      expect(runnerResults.passedCount).toEqual(3);
  97
+
  98
+      expect(spy1.callCount).toEqual(1);
  99
+      expect(spy2.callCount).toEqual(1);
  100
+      expect(spy3.callCount).toEqual(1);
  101
+    });
  102
+  });
  103
+
16 104
   describe('beforeEach', function() {
17 105
     it('should run before each spec for all suites', function () {
18 106
       var foo;
@@ -264,4 +352,4 @@ describe('RunnerTest', function() {
264 352
       expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite3.getFullName()]);
265 353
     });
266 354
   });
267  
-});
  355
+});
16  src/Env.js
@@ -115,6 +115,22 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) {
115 115
   return suite;
116 116
 };
117 117
 
  118
+jasmine.Env.prototype.beforeAll = function(beforeAllFunction) {
  119
+  if (this.currentSuite) {
  120
+    this.currentSuite.beforeAll(beforeAllFunction);
  121
+  } else {
  122
+    this.currentRunner_.beforeAll(beforeAllFunction);
  123
+  }
  124
+};
  125
+
  126
+jasmine.Env.prototype.afterAll = function(afterAllFunction) {
  127
+  if (this.currentSuite) {
  128
+    this.currentSuite.afterAll(afterAllFunction);
  129
+  } else {
  130
+    this.currentRunner_.afterAll(afterAllFunction);
  131
+  }
  132
+};
  133
+
118 134
 jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
119 135
   if (this.currentSuite) {
120 136
     this.currentSuite.beforeEach(beforeEachFunction);
15  src/Runner.js
@@ -8,6 +8,8 @@ jasmine.Runner = function(env) {
8 8
   var self = this;
9 9
   self.env = env;
10 10
   self.queue = new jasmine.Queue(env);
  11
+  self.beforeAll_ = [];
  12
+  self.afterAll_ = [];
11 13
   self.before_ = [];
12 14
   self.after_ = [];
13 15
   self.suites_ = [];
@@ -23,6 +25,16 @@ jasmine.Runner.prototype.execute = function() {
23 25
   });
24 26
 };
25 27
 
  28
+jasmine.Runner.prototype.beforeAll = function(beforeAllFunction) {
  29
+  beforeAllFunction.typeName = 'beforeAll';
  30
+  this.beforeAll_.unshift(beforeAllFunction);
  31
+};
  32
+
  33
+jasmine.Runner.prototype.afterAll = function(afterAllFunction) {
  34
+  afterAllFunction.typeName = 'afterAll';
  35
+  this.afterAll_.unshift(afterAllFunction);
  36
+};
  37
+
26 38
 jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
27 39
   beforeEachFunction.typeName = 'beforeEach';
28 40
   this.before_.splice(0,0,beforeEachFunction);
@@ -33,7 +45,6 @@ jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
33 45
   this.after_.splice(0,0,afterEachFunction);
34 46
 };
35 47
 
36  
-
37 48
 jasmine.Runner.prototype.finishCallback = function() {
38 49
   this.env.reporter.reportRunnerResults(this);
39 50
 };
@@ -74,4 +85,4 @@ jasmine.Runner.prototype.topLevelSuites = function() {
74 85
 
75 86
 jasmine.Runner.prototype.results = function() {
76 87
   return this.queue.results();
77  
-};
  88
+};
21  src/Spec.js
@@ -201,6 +201,27 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
201 201
   for (i = 0; i < runner.after_.length; i++) {
202 202
     this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
203 203
   }
  204
+
  205
+  if (!this.suite.queue.index) {
  206
+    for (i = 0, l = this.suite.beforeAll_.length; i < l; i++) {
  207
+      this.queue.addBefore(new jasmine.Block(this.env, this.suite.beforeAll_[i], this));
  208
+    }
  209
+    if (!runner.queue.index) {
  210
+      for (i = 0, l = runner.beforeAll_.length; i < l; i++) {
  211
+        this.queue.addBefore(new jasmine.Block(this.env, runner.beforeAll_[i], this));
  212
+      }
  213
+    }
  214
+  }
  215
+  if (this.suite.queue.index == this.suite.queue.blocks.length - 1) {
  216
+    for (i = 0, l = this.suite.afterAll_.length; i < l; i++) {
  217
+      this.queue.add(new jasmine.Block(this.env, this.suite.afterAll_[i], this));
  218
+    }
  219
+    if (runner.queue.index == runner.queue.blocks.length - 1) {
  220
+      for (i = 0, l = runner.afterAll_.length; i < l; i++) {
  221
+        this.queue.add(new jasmine.Block(this.env, runner.afterAll_[i], this));
  222
+      }
  223
+    }
  224
+  }
204 225
 };
205 226
 
206 227
 jasmine.Spec.prototype.explodes = function() {
14  src/Suite.js
@@ -14,6 +14,8 @@ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
14 14
   self.queue = new jasmine.Queue(env);
15 15
   self.parentSuite = parentSuite;
16 16
   self.env = env;
  17
+  self.beforeAll_ = [];
  18
+  self.afterAll_ = [];
17 19
   self.before_ = [];
18 20
   self.after_ = [];
19 21
   self.children_ = [];
@@ -37,6 +39,16 @@ jasmine.Suite.prototype.finish = function(onComplete) {
37 39
   }
38 40
 };
39 41
 
  42
+jasmine.Suite.prototype.beforeAll = function(beforeAllFunction) {
  43
+  beforeAllFunction.typeName = 'beforeAll';
  44
+  this.beforeAll_.push(beforeAllFunction);
  45
+};
  46
+
  47
+jasmine.Suite.prototype.afterAll = function(afterAllFunction) {
  48
+  afterAllFunction.typeName = 'afterAll';
  49
+  this.afterAll_.push(afterAllFunction);
  50
+};
  51
+
40 52
 jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
41 53
   beforeEachFunction.typeName = 'beforeEach';
42 54
   this.before_.unshift(beforeEachFunction);
@@ -79,4 +91,4 @@ jasmine.Suite.prototype.execute = function(onComplete) {
79 91
   this.queue.start(function () {
80 92
     self.finish(onComplete);
81 93
   });
82  
-};
  94
+};
24  src/base.js
@@ -516,6 +516,28 @@ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout
516 516
 };
517 517
 
518 518
 /**
  519
+ * A function that is called before all spec in a suite.
  520
+ *
  521
+ * Used for suite setup, including validating assumptions.
  522
+ *
  523
+ * @param {Function} beforeAllFunction
  524
+ */
  525
+var beforeAll = function(beforeAllFunction) {
  526
+  jasmine.getEnv().beforeAll(beforeAllFunction);
  527
+};
  528
+
  529
+/**
  530
+ * A function that is called after all spec in a suite.
  531
+ *
  532
+ * Used for suite setup, including validating assumptions.
  533
+ *
  534
+ * @param {Function} afterAllFunction
  535
+ */
  536
+var afterAll = function(afterAllFunction) {
  537
+  jasmine.getEnv().afterAll(afterAllFunction);
  538
+};
  539
+
  540
+/**
519 541
  * A function that is called before each spec in a suite.
520 542
  *
521 543
  * Used for spec setup, including validating assumptions.
@@ -541,7 +563,7 @@ var afterEach = function(afterEachFunction) {
541 563
  * Defines a suite of specifications.
542 564
  *
543 565
  * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
544  
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
  566
+ * are accessible by calls to beforeAll, afterAll, beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
545 567
  * of setup in some tests.
546 568
  *
547 569
  * @example
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.