thoughtbot / shoulda-matchers

Simple one-liner tests for common Rails functionality
https://matchers.shoulda.io
MIT License
3.51k stars 912 forks source link

Ruby-tests-explorer and shoulda integration #1587

Closed merof-code closed 10 months ago

merof-code commented 10 months ago

I like using ruby-test-explorer and minitest: https://github.com/connorshea/vscode-ruby-test-adapter https://marketplace.visualstudio.com/items?itemName=connorshea.vscode-ruby-test-adapter

And currently it does not work with shoulda tests, at all. I want to use shoulda in my project, so I want to fix that.

This extension works by putting together all the tests info here def build_list. And using file path and line number for opening the test, displaying in UI and running individually.

It does so by extending minitest and collecting all the Minitest::Runnable.runnables.map do |runnable| => runnable_methods

Here is the important part (part of it:) )

::Minitest::Runnable.runnables.map do |runnable|
  file_tests = runnable.runnable_methods.map do |test_name|
    path, line = runnable.instance_method(test_name).source_location
    full_path = File.expand_path(path, VSCode.project_root)
    # path = full_path.gsub(VSCode.project_root.to_s, ".")
    # path = "./#{path}" unless path.match?(/^\./)
    # description = test_name.gsub(/^test_[:\s]*/, "")
    # description = description.tr("_", " ") unless description.match?(/\s/)
    {
      # description: description,
      # full_description: description,
      # file_path: path,
      full_path: full_path,
      line_number: line,
      # klass: runnable.name,
      # method: test_name,
      runnable: runnable
    }
  end
  file_tests.sort_by! { |t| t[:line_number] }
  file_tests.each do |t|
    t[:id] = "#{t[:file_path]}[#{t[:line_number]}]"
  end
  tests.concat(file_tests)
end

JSON that is passed to the extension

Note: line_nuber is used to run the test separately (some fields omitted)

This json works for the extension

{
      "file_path": "./test/models/bank_account_test.rb",
      "full_path": "/home/merof././.bank_account_test.rb",
      "line_number": 16,
      "klass": "BankAccountTest",
      "method": "test_setup_bank_valid",
      "runnable": "BankAccountTest",
      "id": "./test/models/bank_account_test.rb[16]"
    },

This is a json that is returned with shoulda

{
      "file_path": ".//home/merof/.rbenv/versions/3.1.4/lib/ruby/gems/3.1.0/gems/shoulda-context-2.0.0/lib/shoulda/context/context.rb",
      "full_path": "/home/merof/.rbenv/versions/3.1.4/lib/ruby/gems/3.1.0/gems/shoulda-context-2.0.0/lib/shoulda/context/context.rb",
      "line_number": 62,
      "klass": "MyModelTest",
      "method": "test_: validations should validate that :value_type cannot be empty/falsy. ",
      "runnable": "MyModelTest",
      "id": ".//home/merof/.rbenv/versions/3.1.4/lib/ruby/gems/3.1.0/gems/shoulda-context-2.0.0/lib/shoulda/context/context.rb[62]"
    },

And this all can be run by entire dir, file or by file and line number. The last one is interesting for this case. Because we can't run the test by line because it does not exist there, it is in the shoulda gem

def add_file_with_line(file, line)
  test = VSCode::Minitest.tests.find_by(full_path: file, line_number: line)
  raise "There is no test the the given location: #{file}:#{line}" unless test
  runnables << [test[:runnable], filter: test[:method]]
end

So, the question is, how can this be done with shoulda?

PS sorry for being jumbled up a bit, accidentally submitted with ctrl+enter before finished refining.

matsales28 commented 10 months ago

Hi @merof-code, unfortunately, I don't think we could do much on the shoulda-matchers side to help with that. It's probably necessary to revisit how the vs code extension defines the file_path of the specs/matchers defined outside the app code. I'm closing this issue, but please feel free to re-open it if we can do something to help you with that.