Skip to content

Conversation

luke-hill
Copy link

🤔 What's changed?

This is a first attempt at a porting over for the first of many items I need to port

⚡️ What's your motivation?

Use the standard query structure that java / js use

🏷️ What kind of change is this?

  • 🏦 Refactoring/debt/DX (improvement to code design, tooling, etc. without changing behaviour)
  • ⚡ New feature (non-breaking change which adds new behaviour)
  • 💥 Breaking change (incompatible changes to the API)

♻️ Anything particular you want feedback on?

I'm not looking to "implement" this for a good 3-6 months, owing to the fact this is something that is a slow burner and I'm convinced some bits are wrong for the existing implementation we have in cucumber-ruby

📋 Checklist:

TBC. Need to agree what needs porting, what needs creating, and what needs adapting

Copy link
Contributor

@mpkorstanje mpkorstanje left a comment

Choose a reason for hiding this comment

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

It looks like you're writing tests for each method. That isn't necessary.

Rather you can define a list of sources:

  • "../testdata/attachments.ndjson"
  • "../testdata/empty.ndjson"
  • "../testdata/hooks.ndjson"
  • "../testdata/minimal.ndjson"
  • "../testdata/rules.ndjson"
  • "../testdata/examples-tables.ndjson"

And a map of query functions queries of the form (Query query) -> /* execute some query and return the results*/. For example:

queries.put("findAllTestStepsStarted", (query) -> query.findAllTestStepsStarted().size());

Then take the product of sources and queries and for each of those populate a instance of the Query object with the messages from the source, and then apply the query function to the Query object.

Then you compare the result of query function to the ../testdata/<source>.<methodname>.results.json file.

The nice thing is that you can add methods to the queries list as you implement them.

@luke-hill
Copy link
Author

Atm I'm copying over things that already exist. I'm well aware this is likely wrong. I just want to get what currently "works" in here and equivalent passing/failing.

See https://github.com/cucumber/cucumber-ruby/tree/main/lib/cucumber/formatter/query for where I'm adapting things from for now.

Copy link
Contributor

@mpkorstanje mpkorstanje left a comment

Choose a reason for hiding this comment

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

Some other nitpicks below, but I suppose those are there because this is WIP


s.add_dependency 'cucumber-messages', '> 25', '< 30'

s.add_development_dependency 'cucumber', '~> 10.1'
Copy link
Contributor

Choose a reason for hiding this comment

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

?

'bug_tracker_uri' => 'https://github.com/cucumber/query/issues',
'changelog_uri' => 'https://github.com/cucumber/query/blob/main/CHANGELOG.md',
'documentation_uri' => 'https://github.com/cucumber/query/blob/main/CONTRIBUTING.md',
'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/cukes',
Copy link
Contributor

Choose a reason for hiding this comment

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

?

s.metadata = {
'bug_tracker_uri' => 'https://github.com/cucumber/query/issues',
'changelog_uri' => 'https://github.com/cucumber/query/blob/main/CHANGELOG.md',
'documentation_uri' => 'https://github.com/cucumber/query/blob/main/CONTRIBUTING.md',
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be the read me I guess, not the contributors guide.

def hook_id(test_step)
return @hook_id_by_test_step_id[test_step.id] if @hook_id_by_test_step_id.key?(test_step.id)

raise TestStepUnknownError, "No hook found for #{test_step.id} }. Known: #{@hook_id_by_test_step_id.keys}"
Copy link
Contributor

Choose a reason for hiding this comment

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

The design of the query object assumes that if something can't be found either an empty list, empty optional or null is returned. There are no methods that throw.

This is also why all the methods are name findX or findAllX or findZByX`.

@mpkorstanje
Copy link
Contributor

Atm I'm copying over things that already exist. I'm well aware this is likely wrong. I just want to get what currently "works" in here and equivalent passing/failing.

That doesn't seem like a good idea. The query object is used by the xml, json, pretty formatters, ect. By using a different API the Ruby implementations of these will lose the resemblance to the Java and Javascript versions. That will make maintenance much harder.

I think you'd be better of leaving that old query object in place, implement the new query object here, then migrate your users of the old query object over to the new query object instead.

@mpkorstanje mpkorstanje marked this pull request as draft September 5, 2025 18:27
@mpkorstanje mpkorstanje changed the title WIP: Ruby implementation Ruby implementation Sep 5, 2025
@mpkorstanje
Copy link
Contributor

Removed WIP from title, marked PR as draft.

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

Successfully merging this pull request may close these issues.

2 participants