junit-team / junit4

A programmer-oriented testing framework for Java.
https://junit.org/junit4
Eclipse Public License 1.0
8.51k stars 3.25k forks source link

@Rules annotation at class level #200

Open dsaff opened 13 years ago

dsaff commented 13 years ago

[text extracted from AlistairIsrael's https://github.com/KentBeck/junit/issues/32] Merely voicing out an idea here that came to mind as I've been using @Rules. I'd like to put it in here just for the record, but if you guys have a better idea for the direction @Rules should go I'd be happy to go with that.

Currently, to use a rule the test class has to declare and instantiate the Rule object, like so:

    @Rule
    public MagicMocker magicMocker = new MagicMocker();

Basically, I can see myself, and others, coming up with quite a few rules that the test itself doesn't interact with (and that have default constructors).

My idea is to let the test simply declare any such rules, using another annotation, and have JUnit take care of instantiation.

JUnit already instantiates the test classes themselves, so I don't see why it can't instantiate other things. JUnit also already provides class-level annotations that affect test behavior (@RunWith) so I think whole the idea isn't entirely foreign to JUnit.

For example,

@Rules({TestPersistenceContext.class, FixturesLoader.class})
public class DaoTest {

In the above, JUnit could take care of instantiating, then applying the rules that set up the test database and load data fixtures. The FixturesLoader.class could be a MethodRule that gets applied to all test methods. The resulting test code is more concise and less cluttered with rules/fixture setup.

dsaff commented 13 years ago

What if the magic were:

public class DaoTest {
   public @Rule TestRule all = Rules.fromClasses(TestPersistenceContext.class, FixturesLoader.class);

Or:

public class DaoTest {
   public @Rule TestRule all = Rules.inOrder(new TestPersistenceContext(), new FixturesLoader(), new Timeout(2000));

It's five more tokens, but would work without changing current code.

matthewfarwell commented 12 years ago

Is RuleChain a good candidate for this?

Another alternative would be to add a couple of convenience methods to RuleChain which take a Class<? extends TestRule> and builds up a chain, or a list of TestRule which builds up a chain.

In the case of the Class<>, we could instantiate them.

dsaff commented 12 years ago

I've come around to the idea of @Rules as expressed here.

matthewfarwell commented 12 years ago

Ok. I'll do a pull with the @rules, but I'll probably include the same or similar functionality in RuleChain as well.

One use case that I foresee is to have a set of tests which all have the same rules, so if i use @rules like you suggested, I'd have to copy that line multiple times. Also, if there is some interaction with the test, then we'd have to use RuleChain.

nolah commented 11 years ago

Hi, is someone working on this, it would be a great feature?

dsaff commented 11 years ago

@nolah, as far as I know, this has dropped off our radar. Want to give it a try?

nolah commented 11 years ago

I think I will.

ghost commented 11 years ago

Hello, I use few rules with constructors without arguments, so I think, it's good idea. I implemented it as an exercise, but I'm new in this team and I don't know what should I do now. Could I commit my changes? Where? Could someone check my changes?

dsaff commented 11 years ago

@jarekdabrowski, you should submit a pull request (refer to the github documentation for how to go about it).

That said, before putting a lot of work into the code and pull request, I'd love to hear your opinion on why @Rules as proposed as a top-level construct is definitely better than my proposal in https://github.com/junit-team/junit/issues/200#issuecomment-847514

ghost commented 11 years ago

I expressed my thought not very clearly. I implemented your proposal, I think it's useful feature.

kcooney commented 10 years ago

Going through old bugs...

@jarekdabrowski Did you have an implementation that you would be willing to contribute?

Personally, I'm fine with:

public class DaoTest {
  public @Rule TestRule all = RuleChain.fromClasses(
      TestPersistenceContext.class, FixturesLoader.class);

We may be able to solve this with meta annotations, but I'm not sure if we can guarantee ordering. See https://github.com/junit-team/junit/issues/766#issuecomment-29310353 for a thumbnail sketch