Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Add before_register hook to RSpec World #2094

Merged
merged 1 commit into from
Oct 22, 2015
Merged

Add before_register hook to RSpec World #2094

merged 1 commit into from
Oct 22, 2015

Conversation

bootstraponline
Copy link
Contributor

Fix #2078

Use case:

Enables running an unmodified test suite on multiple Selenium browsers.

# Invokes block before registering an example group
def before_register(&block)
before_register_callbacks << block
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should go on config instead of world. Config is where we let users configure callbacks.

Also, example group registration isn't really a concept we've exposed into our API up to now. It's purely an internal. I think that this feature would fit better with RSpec's terminology if it was something like on_example_group_definition, e.g.:

RSpec.configure do |c|
  c.on_example_group_definition do |example_group|
    # do something with the newly defined example group
  end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'll fix.

@bootstraponline
Copy link
Contributor Author

I updated the PR to use on_example_group_definition instead of before_register. I also fixed the spec so it shows a supported use case. If there's a better way to accomplish the goal without this hook then that'd be great as well.

@myronmarston
Copy link
Member

@bootstraponline I think what you have here is reasonable as far as a way to hook in to example group creation in RSpec. But to generate additional examples that are essentially clones of existing ones w/ some modifications, we should provide you with some new APIs. Here's what I'm thinking...

  • ExampleGroup needs new public APIs like ExampleGroup.add_example and ExampleGroup.remove_example
  • Example needs a new public API like duplicate_with(metadata_overrides).

Then for your case I think you could do something like this:

RSpec.configure do |config|
  config. on_example_group_definition do |group|
    group.examples.each do |example|
      group.remove_example example

      [{:browserName => :firefox}, {:browserName => :chrome}].each do |cap|
        group.add_example example.duplicate_with(:cap => cap)
      end
    end
  end
end

Thoughts?

@bootstraponline
Copy link
Contributor Author

That looks awesome!

@myronmarston
Copy link
Member

That looks awesome!

Want to open up PRs adding those APIs? (and/or add them to this one)?

@bootstraponline
Copy link
Contributor Author

Want to open up PRs adding those APIs? (and/or add them to this one)?

I think they're better as independent PRs. I'll work on submitting a new PR for ExampleGroup and another for Example.

add_example/remove_example should be easy. duplicate_with is a bit more tricky since rspec will delete tests if they share the same id so I'll have to change it to something else (maybe add a hash of the metadata?).

@myronmarston
Copy link
Member

duplicate_with is a bit more tricky since rspec will delete tests if they share the same id so I'll have to change it to something else (maybe add a hash of the metadata?).

I'd recommend not doing anything with the ids. In fact, don't even use dup or clone -- instead, just instantiate a new instance of Example and RSpec will take care of the rest. Essentially you'd do something similar to what RSpec does here:

desc, *args = *all_args
options = Metadata.build_hash_from(args)
options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
options.update(extra_options)
example = RSpec::Core::Example.new(self, desc, options, block)

In fact, it might be as simple as:

Example.new(example.example_group_class, example.description, example.metadata, example.example_block)

@bootstraponline
Copy link
Contributor Author

Ok, I'll try it.

@bootstraponline
Copy link
Contributor Author

I squashed to one commit and Travis is passing. appveyor had an internal server error unrelated to the PR.

@bootstraponline
Copy link
Contributor Author

I submitted #2095 for add/remove example. Working on duplicate_with next.

@JonRowe
Copy link
Member

JonRowe commented Oct 22, 2015

LGTM

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 this pull request may close these issues.

3 participants