rubyautomationminitestparametrized-testing

Is there a possibility to write parametrized tests with Ruby+Minitest?


I've recently started working on a automated testing project, that uses Ruby+Minitest and I wonder if I can run 1 test as many times as many input data I provide.

So, I have smth like (code is under NDA so I can't provide real examples)

def test_new_registrations
  result = process_new_entry(list_entries)
  assert(validator_method(result), result)
end

The trick is that inside process_new_entry method there's a loop I'm glad to get rid of and just run this test as many times as many entries are there on the list_entries

From TestNG in Java+Selenium I recall a concept of using a dataprovider which passes input data inside the test method one by one. Is there any chance a simmilar approach can be implemented here?


Solution

  • If you have:

    class MyTest
      TESTCASES = {
        # input => expected
        a: "a",
        b: "b",
        c: "c",
      }
    
      def test_testcases
        TESTCASES.each do |entry, expected|
          result = process_one(entry)
          assert(expected, result)
        end
      end
    end
    

    And you really want to run each case in its own test instead, then it's just:

    MyTest
      TESTCASES = {
        # input => expected
        a: "a",
        b: "b",
        c: "c",
      }
    
      TESTCASES.each do |entry, expected|
        define_method("test_testcase_#{entry}") do
          result = process_one(entry)
          assert(expected, result)
        end
      end
    end
    

    If you REALLY wanted to have the exact same syntax as in Java, it'd be possible to convert the above into a library so that this would work:

    testcase_parameters(TESTCASES) # left as an exercise to the reader
    def test_testcase(entry, expected)
      assert(expected, process_one(entry))
    end
    

    But I don't see the benefit of being so indirect/abstract about it. I would suggest to stay explicit, keeping the code and execution state inspect-able and easy to debug:

    class MyTest
      TESTCASES = {
        # input => expected
        a: "a",
        b: "b",
        c: "c",
      }
    
      def test_testcases
        results = TESTCASES.map do |entry, expected|
          result = process_one(entry)
          [entry, [expected, result]]
        end
    
        invalid_results = results.select { |e, (ex, res)| ex != res }
    
        # This is a very easy-to-breakpoint place in code, to easily view all results:
        # binding.pry
    
        assert_empty invalid_results # failure cases will be printed out by test output
      end
    end