I know there is a balance to be struck between writing dry code and damp code but I have the feeling that this is a bit too repeative. Is there a terse yet self explainatory way to rewrite these tests?
class TripTest < ActiveSupport::TestCase
def setup
@trip = trips(:one)
@invoice = invoices(:one)
end
test 'trip can save' do
trip = Trip.new
trip.departure_date = "2040-03-24"
trip.depart_airport = "DHW"
trip.arrive_airport = "ABC"
trip.invoice_id = 123534
assert trip.save, "Error message: #{trip.errors.full_messages}"
end
test "one invoice can have multiple trips" do
trip = Trip.new
trip.departure_date = "2040-03-24"
trip.depart_airport = "DHW"
trip.arrive_airport = "ABC"
trip.invoice_id = 123534
@invoice.trips.push(trip)
@invoice.save
trip = Trip.new
trip.departure_date = "2040-03-24"
trip.depart_airport = "ICN"
trip.arrive_airport = "XYZ"
trip.invoice_id = 123534
@invoice.trips.push(trip)
@invoice.save
assert @invoice.trips.size > 1
end
1 Answer 1
If you're writing verbose tests, your test suite will skyrocket in length.
There are worse problems to have but your best asset to address this problem is a comprehensive test_helper
class.
It doesn't matter what you call the file. Just load it up into your main test file with a require_relative
.
In your example, it's fairly obvious which code is being repeated between methods. So you could refactor your code as follows:
# in test_helpers.rb
module TestHelpers
def initialize_sample_trip(options={})
Trip.new(
departure_date: options[:departure_date] || "2040-03-24"
default_airport: options[:default_airport] || "DHW"
arrive_airport: options[:arrive_airport] || "ABC"
invoice_id: options[:invoice_id] || 123534
)
end
end
...
# in your main test file
require_relative './test_helpers.rb'
class TripTest < ActiveSupport::TestCase
include TestHelpers
def setup
@trip = trips(:one)
@invoice = invoices(:one)
end
test 'trip can save' do
trip = initialize_sample_trip
assert trip.save, "Error message: #{trip.errors.full_messages}"
end
test "one invoice can have multiple trips" do
trip1 = initialize_sample_trip
@invoice.trips.push(trip1)
@invoice.save
trip2 = initialize_sample_trip(
depart_airport: ICN, arrive_airport: "XYZ"
)
@invoice.trips.push(trip)
@invoice.save
assert @invoice.trips.size > 1
end
This can be considered a "factory" design pattern. There are also various gems which can assist with this such as factory_girl or faker.