Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

BeforeClass being called for each Parameter #52

Closed
nioncode opened this issue May 7, 2015 · 3 comments · Fixed by #53
Closed

BeforeClass being called for each Parameter #52

nioncode opened this issue May 7, 2015 · 3 comments · Fixed by #53
Assignees

Comments

@nioncode
Copy link

nioncode commented May 7, 2015

Currently, @BeforeClass methods get invoked once for the test class and then again every time a new Class Parameter combination gets tested the first time.
The code below will result in a sequence of messages like:

test: beforeClass
test: beforeClass
test: (param1 SMALL, param2 ENABLED) -> SquareBurst constructor
test: (size: SMALL, param2 ENABLED) -> before
test: (param1 SMALL, param2 ENABLED) -> test1
test: (param1 SMALL, param2 ENABLED) -> SquareBurst constructor
test: (size: SMALL, param2 ENABLED) -> before
test: (param1 SMALL, param2 ENABLED) -> test2
test: (param1 SMALL, param2 ENABLED) -> SquareBurst constructor
test: (size: SMALL, param2 ENABLED) -> before
test: (param1 SMALL, param2 ENABLED, methodParameter: SMALL) -> someShortTest
test: (param1 SMALL, param2 ENABLED) -> SquareBurst constructor
test: (size: SMALL, param2 ENABLED) -> before
test: (param1 SMALL, param2 ENABLED, methodParameter: MEDIUM) -> someShortTest
test: beforeClass
test: (param1 MEDIUM, param2 ENABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 ENABLED) -> before
test: (param1 MEDIUM, param2 ENABLED) -> test1
test: (param1 MEDIUM, param2 ENABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 ENABLED) -> before
test: (param1 MEDIUM, param2 ENABLED) -> test2
test: (param1 MEDIUM, param2 ENABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 ENABLED) -> before
test: (param1 MEDIUM, param2 ENABLED, methodParameter: SMALL) -> someShortTest
test: (param1 MEDIUM, param2 ENABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 ENABLED) -> before
test: (param1 MEDIUM, param2 ENABLED, methodParameter: MEDIUM) -> someShortTest
test: beforeClass
test: (param1 LARGE, param2 ENABLED) -> SquareBurst constructor
test: (size: LARGE, param2 ENABLED) -> before
test: (param1 LARGE, param2 ENABLED) -> test1
test: (param1 LARGE, param2 ENABLED) -> SquareBurst constructor
test: (size: LARGE, param2 ENABLED) -> before
test: (param1 LARGE, param2 ENABLED) -> test2
test: (param1 LARGE, param2 ENABLED) -> SquareBurst constructor
test: (size: LARGE, param2 ENABLED) -> before
test: (param1 LARGE, param2 ENABLED, methodParameter: SMALL) -> someShortTest
test: (param1 LARGE, param2 ENABLED) -> SquareBurst constructor
test: (size: LARGE, param2 ENABLED) -> before
test: (param1 LARGE, param2 ENABLED, methodParameter: MEDIUM) -> someShortTest
test: beforeClass
test: (param1 SMALL, param2 DISABLED) -> SquareBurst constructor
test: (size: SMALL, param2 DISABLED) -> before
test: (param1 SMALL, param2 DISABLED) -> test1
test: (param1 SMALL, param2 DISABLED) -> SquareBurst constructor
test: (size: SMALL, param2 DISABLED) -> before
test: (param1 SMALL, param2 DISABLED) -> test2
test: (param1 SMALL, param2 DISABLED) -> SquareBurst constructor
test: (size: SMALL, param2 DISABLED) -> before
test: (param1 SMALL, param2 DISABLED, methodParameter: SMALL) -> someShortTest
test: (param1 SMALL, param2 DISABLED) -> SquareBurst constructor
test: (size: SMALL, param2 DISABLED) -> before
test: (param1 SMALL, param2 DISABLED, methodParameter: MEDIUM) -> someShortTest
test: beforeClass
test: (param1 MEDIUM, param2 DISABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 DISABLED) -> before
test: (param1 MEDIUM, param2 DISABLED) -> test1
test: (param1 MEDIUM, param2 DISABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 DISABLED) -> before
test: (param1 MEDIUM, param2 DISABLED) -> test2
test: (param1 MEDIUM, param2 DISABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 DISABLED) -> before
test: (param1 MEDIUM, param2 DISABLED, methodParameter: SMALL) -> someShortTest
test: (param1 MEDIUM, param2 DISABLED) -> SquareBurst constructor
test: (size: MEDIUM, param2 DISABLED) -> before
test: (param1 MEDIUM, param2 DISABLED, methodParameter: MEDIUM) -> someShortTest
test: beforeClass
test: (param1 LARGE, param2 DISABLED) -> SquareBurst constructor
test: (size: LARGE, param2 DISABLED) -> before
test: (param1 LARGE, param2 DISABLED) -> test1
test: (param1 LARGE, param2 DISABLED) -> SquareBurst constructor
test: (size: LARGE, param2 DISABLED) -> before
test: (param1 LARGE, param2 DISABLED) -> test2
test: (param1 LARGE, param2 DISABLED) -> SquareBurst constructor
test: (size: LARGE, param2 DISABLED) -> before
test: (param1 LARGE, param2 DISABLED, methodParameter: SMALL) -> someShortTest
test: (param1 LARGE, param2 DISABLED) -> SquareBurst constructor
test: (size: LARGE, param2 DISABLED) -> before
test: (param1 LARGE, param2 DISABLED, methodParameter: MEDIUM) -> someShortTest

As can be seen, the @BeforeClass annotated method gets invoked multiple times.
My test methods need some resources that are read only and thus can be shared. However, it takes multiple seconds to create these, so I'd like to initialize them once for the entire test class.

I propose, BeforeClass should be called once for every test class, not for every new combination of Class Parameters. This is how JUnit's Parameterized Class does it as well.

Also, it would be great to have a new annotation that can be used to invoke a method every time a new Class Parameter combination is created, just like @BeforeClass does now, but give it access to the newly created Class Parameter combination, so that it can be used to do a one time setup and teardown for each Class Parameter combination.

Example Code:

@RunWith(BurstJUnit4.class)
public class SquareBurst {

    public enum Parameter1 { SMALL, MEDIUM, LARGE }
    public enum Parameter2 { ENABLED, DISABLED }
    public enum MethodParameter { SMALL, MEDIUM }

    @Before
    public void before() {
        System.out.println(String.format("test: (size: %s, param2 %s) -> before", size, parameter2));
    }

    @BeforeClass
    public static void beforeClass() {
        System.out.println("test: beforeClass");
    }

    private Parameter1 size;
    private Parameter2 parameter2;

    public SquareBurst(Parameter2 parameter2, Parameter1 size) {
        System.out.println(String.format("test: (param1 %s, param2 %s) -> SquareBurst constructor", size, parameter2));
        this.size = size;
        this.parameter2 = parameter2;
    }

    @Test
    public void someShortTest(MethodParameter methodParameter) {
        System.out.println(String.format("test: (param1 %s, param2 %s, methodParameter: %s) -> someShortTest",
                                         size, parameter2, methodParameter));
    }

    @Test
    public void test1() {
        System.out.println(String.format("test: (param1 %s, param2 %s) -> test1", size, parameter2));
    }

    @Test
    public void test2() {
        System.out.println(String.format("test: (param1 %s, param2 %s) -> test2", size, parameter2));
    }

}
@JakeWharton
Copy link
Member

I propose, BeforeClass should be called once for every test class, not for every new combination of Class Parameters. This is how JUnit's Parameterized Class does it as well.

Yes. This is a clear bug.

@dlubarov dlubarov self-assigned this May 7, 2015
dlubarov added a commit that referenced this issue May 7, 2015
`BurstJUnit4` already invokes them once for the whole class, so the `BurstRunner`s should just no-op.

Fixes #52.
@dlubarov
Copy link
Contributor

dlubarov commented May 7, 2015

Thanks for the detailed bug report.

A separate annotation like @BeforeVariation seems like a good idea; I'll try adding that later after the fix is in.

@nioncode
Copy link
Author

nioncode commented May 9, 2015

Awesome, thanks for the fast fix. Looking forward to the @BeforeVariation annotation.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants