-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add Before and After Parameterized Run annotations #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The goal of this request is to have a place to put code that runs before and after a parameter run executes. Not before each test in a given parameter run. Thus the order would be BP BT T1p1 AT BT T2p1 AT BT T3p1 AT AP BP BT T1p2 AT BT T2p2 AT ... where
I had this implemented on my github, however had to take it down due to issues with my employer. I issued a pull to David Saff and he included it in his branch, but it was taken out later. I'll look for the revision number where the code was included after this message. |
Looks like the merge was to a tree of dsaff around April 3, 2009. In the comments you can see a merge from bigmikef. It is way out of date, but did work at the time. |
guys, "after / before" for every parameterized run would be very useful. |
This can be done using rules, in particular ExternalResource. The implemented methods are called for each parameter:
This produces
If this is acceptable, please close this issue. |
@matthewfarwell I may be misunderstanding your response, but in the example you provided that rule would run before and after each test for each instance created by the parameterized runner. What I think @bigmikef wanted was the capability to be able to run a before and after method once for each instance created by the parameterized runner. I don't think @ClassRule can be used in this case because that runs in a static context and is only executed once for all parameterized instances. |
I wouldn't mind taking the initiative to implement this since it would be beneficial in my current project. My proposal is below: Summary of Implementation:The traditional architecture of JUnit is a instance of a Java class per test method. In order to implement the requirements above I believe the The primary reason for this is so the logic executed before and after each parameterized run is local to the class and not put in some global scope with a static modifier. In my particular use case I have setup and tear down that would require use of parameters that are unique to each parameterized instance. Additions / Modifications:
|
@coreyjv what's wrong with @matthewfarwell `s answer? |
@Tibor17 , see my response to his answer: https://github.com/KentBeck/junit/issues/45#issuecomment-11293228 His implementation is executed before and after each test method. In my case, my setup and tear down is significantly expensive which is why I want to execute it before and after each parameterized run. For example if I have a test class that when executed once with a common setup (located in a @ClassRule currently) the entire class executes and completes the tests in ~20 seconds. However, if I move the setup to a method level rule it takes approximately ~240 seconds to execute and complete. That's just for one class. In my situation that increase in time is not acceptable. Theoretically I could place all my tests in a single method to emulate the required behavior but I don't think that is a maintainable test design. |
@coreyjv |
@Tibor17, essentially yes. I think I'd use a single annotation that allowed rules to execute. |
If I used the BeforeClass (BC) and AC, then would it look like this ? |
@Tibor17, yes I believe what you've presented is accurate. |
@coreyjv |
@Tibor17 My needs resulted in a JUnit test class per page to test for things such as:
These pages may be at any arbitrary depth inside the application so I put the navigational logic to get to the destination page in a "before" rule (currently @ClassRule). Ideally, I'd like to run the same test with different parameters, which are read and used in in the "setup." These parameters would be items like user identifier and password credentials and other particulars that are relevant to getting to the destination page. I'll quote a previous response I wrote as to why I want to do it per "lifecycle":
|
@coreyjv |
@Tibor17, correct the parameters have to be visible in the setup. What kind of additional clarification or details would you like me to provide? I think the overview and my previous comments provide a good picture of my need (you can see the mailing list as well) without going into the specifics of the application which I think would add limited value. |
@coreyjv |
@Tibor17 |
@coreyjv |
Are you looking for me to post a sample test class? It's really be pretty boring since it is just like any other parameterized test (where the parameters are read from a database for example) and "life cycle" setup would be used in place of @ClassRule or @rule setup. As I've previously mentioned a simple case would be setup which used different combinations of usernames, passwords and application roles. I don't think it's that out of the ordinary. It is just in this case the setup is prohibitively expensive to do before and after each method. |
What about doing this in your test
|
@Tibor17 |
@coreyjv |
@Tibor17 |
Thoughts:
a. Add an annotation or annotation parameter to enable the different behavior. I think I prefer c to b, and b to a, but open to discussion. |
Thank you!
I implemented my requirements this morning, and I ended up not modifying this method signature (I went with the approach of changing certain internal methods from private --> protected).
I'll take a look at this and keep it in mind.
My implementation is conditional on the existence of a @ParameterRule annotation. If it detects a method or field is annotated with this annotation it will change the instantiation pattern of Parameterized.
See above.
This could most definitely be implemented as a subclass and I would be fine with that as well. My thought process was to work with the existing class because that seemed to be the intent of the originator.
I'm not sure I follow completely, but could I still achieve the requirement of having a common setup that is executed once per array of parameters returned from the @parameters method? Would you prefer I submit a pull request so we have actual code to discuss? |
@coreyjv, yes, I think if you have code you're happy to share, that's a great next step. Thanks! |
Sounds good, I'll try and get a pull request together in the next couple of days. |
- Add a new annotation named ParameterRule. - Add a new protected inner class that extends TestClassRunnerForParameters named SingleInstanceRunnerForParameters. - Instantiates TestClassRunnerForParameters or SingleInstanceRunnerForParameters depending if ParameterRule exists or not. - Modified BlockJUnit4ClassRunner by converting some methods from private to protected.
* Converted `BlockJUnit4ClassRunner` methods back to private * Added `superCreateTest` and overriden `createTest` to `SingleInstanceTestClassRunnerForParameters`
- Add a new annotation named ParameterRule. - Add a new protected inner class that extends TestClassRunnerForParameters named SingleInstanceRunnerForParameters. - Instantiates TestClassRunnerForParameters or SingleInstanceRunnerForParameters depending if ParameterRule exists or not.
Was there ever any resolution to this issue? We have some Junit tests that use the parameter option to specify different browsers, such as IE/Firefox/Chrome, and it was launching a new browser for each test, but to increase the speed of running the tests I was trying to switch to starting and stopping the browsers around a class of tests. If I use the beforeClass and afterClass then there is too much time between one of the parameters finishing and closing the browser, so the remote web driver times out. I would like to use this AfterParameterRun approach, but I see a lot of discussion, and this issue leading to a couple pull requests, but It doesn't look like anything was ever merged into main? |
I too have a case where I'd like to see an 'AfterParameter' function. |
@coreyjv Is this functionality in the pipeline because we are running Parameterized Test Cases where we need such annotations. Both @BeforeParam and @AfterParam are required. |
I see that "@BeforeParam/@AfterParam for Parameterized runner #1435" got merged and added to the 4.13 release notes. Does that mean there's going to be a 4.13 release? When? I'm in dire need of this functionality! I didn't see it in JUnit 5, so I'm wondering when I can expect @BeforeParam/@AfteParam to be available. |
@dstaraster currently most of the JUnit team is focusing on releasing JUnit 5.0. I hope that soon after that we can start on the 4.13 release. |
@kcooney I'm also very interested in these @BeforeParam and @AfterParam annotations (and unfortunately not yet ready to migrate my thousands of tests to JUnit5). |
Currently there is no simple way for a method to be invoked before or after a Parameterized instance is ran.
Said another way, along with @BeforeClass and @afterclass there should be @BeforeParameterRun @AfterParameterRun. Each fires before/after a Parameterized instance is ran.
The text was updated successfully, but these errors were encountered: