Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing 201

Testing 201

Joseph Mastey

April 15, 2019
Tweet

More Decks by Joseph Mastey

Other Decks in Technology

Transcript

  1. class CreateShipmentHistoryReport attr_accessor :user, :shipments def initialize(user) @user = user

    @shipments = user.shipments end def process shipments.sort_by(&:created_at) data = shipments.map do |shipment| shipment.to_json.values + [ shipment.user.name, shipment.product.name ] end file = CSV.open(tmp_filename) do |csv| csv << shipments.first.to_json.keys + ['user', 'product'] data.map do |row| csv << row end end persist_csv_to_s3(file) notify_user(user.email) file end end
  2. def process shipments.sort_by(&:created_at) data = shipments.map do |shipment| shipment.to_json.values +

    [ shipment.user.name, shipment.product.name ] end # continued below...
  3. # ... process continued file = CSV.open(tmp_filename) do |csv| csv

    << shipments.first.to_json.keys + ['user', 'product'] data.map do |row| csv << row end end persist_csv_to_s3(file) notify_user(user.email) file end
  4. class CreateShipmentHistoryReport attr_accessor :user, :shipments def initialize(user) @user = user

    @shipments = user.shipments end def process shipments.order('created_at desc') data = shipments.map do |shipment| shipment.to_json.values + [ shipment.user.name, shipment.product.name ] end file = CSV.open(tmp_filename) do |csv| csv << shipments.first.to_json.keys + ['user', 'product'] data.map do |row| csv << row end end persist_csv_to_s3(file) notify_user(user.email) file end end
  5. describe CreateShipmentHistoryReport do describe "#process" do it "generates an array

    of strings" do expect(csv_data.length).to eq(shipments.length) expect(csv_data).to all(be_an(Array)) end it "generates an output record for each input, sorted by date" do expect(csv_data).to eq(output_records) end end end
  6. let(:product) { create(:product) } let!(:shipment) { create(:shipment, product: product, created_at:

    2.days.ago) } let(:output_records) do [ [shipment.created_on, shipment.completed_on, user.name, product.name] ] end before do expect(user) .to receive(:shipments) .and_return([shipment]) end end
  7. let!(:shipment_1) { create(:shipment, product: product_1, created_at: 2.days.ago) } let!(:shipment_2) {

    create(:shipment, product: product_2, created_at: 3.days.ago) } let!(:shipment_3) { create(:shipment, product: product_3, created_at: 4.days.ago) } let!(:shipment_4) { create(:shipment, product: product_4, created_at: 5.days.ago) }
  8. let(:output_records) do [ [shipment_4.created_on, shipment_4.completed_on, user.name, product_4.name], [shipment_3.created_on, shipment_3.completed_on, user.name,

    product_3.name], [shipment_2.created_on, shipment_2.completed_on, user.name, product_2.name], [shipment_1.created_on, shipment_1.completed_on, user.name, product_1.name], ] end
  9. it "generates an output record for each input, sorted by

    date" do expect(csv_data).to eq(output_records) end
  10. describe CreateShipmentHistoryReport do describe "#process" do let(:user) { create(:user, :signup_complete)

    } let(:subscription) { create(:subscription) } let(:product_1) { create(:product) } let(:product_2) { create(:product) } let(:product_3) { create(:product) } let(:product_4) { create(:product) } let!(:shipment_1) { create(:shipment, product: product_1, created_at: 2.days.ago) } let!(:shipment_2) { create(:shipment, product: product_2, created_at: 3.days.ago) } let!(:shipment_3) { create(:shipment, product: product_3, created_at: 4.days.ago) } let!(:shipment_4) { create(:shipment, product: product_4, created_at: 5.days.ago) } let(:subject) { described_class.new(user).process } let(:csv_data) { CSV.parse(subject) } let(:shipments) do [ shipment_1, shipment_2, shipment_3, shipment_4 ] end let(:output_records) do [ [shipment_4.created_on, shipment_4.completed_on, user.name, product_4.name], [shipment_3.created_on, shipment_3.completed_on, user.name, product_3.name], [shipment_2.created_on, shipment_2.completed_on, user.name, product_2.name], [shipment_1.created_on, shipment_1.completed_on, user.name, product_1.name], ] end before do user.subscription << subscription expect(user) .to receive(:shipments) .and_return(shipments) expect_any_instance_of(described_class) .to receive(:save_to_s3) .and_return(true) expect_any_instance_of(described_class) .to receive(:email_user) .and_return(true) end it "generates an array of strings" do expect(csv_data.length).to eq(shipments.length) expect(csv_data).to all(be_an(Array)) end it "generates an output record for each input, sorted by date" do expect(csv_data).to eq(output_records) end end end
  11. let(:csv_data) { CSV.parse(subject) } before do expect_any_instance_of(described_class) .to receive(:save_to_s3) .and_return(true)

    expect_any_instance_of(described_class) .to receive(:email_user) .and_return(true) end
  12. def data(shipments) shipments.sort_by!(&:created_at) shipments.map do |shipment| shipment.to_json.values + [ shipment.user.name,

    shipment.product.name ] end end def headers shipments.first.to_json.keys + ['user', 'product'] end
  13. it "generates an output record for each input, sorted by

    date" do subject = described_class.new(user) expect(subject.data).to eq(output_records) end
  14. before do # expect_any_instance_of(described_class) # .to receive(:save_to_s3) # .and_return(true) #

    expect_any_instance_of(described_class) # .to receive(:email_user) # .and_return(true) end
  15. def data(shipments) shipments.sort_by!(&:created_at) shipments.map do |shipment| shipment.to_json.values + [ shipment.user.name,

    shipment.product.name ] end end def headers shipments.first.to_json.keys + ['user', 'product'] end
  16. def serialize(shipment) { created_on: shipment.created_on, completed_on: shipment.completed_on, user: shipment.user.name, product:

    shipment.product.name, } end def data(shipments) shipments.sort_by(&:created_at).map do |shipment| serialize(shipment) end end def headers serialize(shipments.first).keys end
  17. describe "#serialize" do it "serializes some shipment and user data"

    do shipment = create_shipment(date: 2.days.ago) report = described_class.new(user, []) result = report.serialize(shipment) expect(result).to eq({ created_on: shipment.created_on, completed_on: shipment.completed_on, user: shipment.user.name, product: shipment.product.name, }) end end
  18. # let(:output_records) do # [ # [shipment_4.created_on, shipment_4.completed_on, # user.name,

    product_4.name], # [shipment_3.created_on, shipment_3.completed_on, # user.name, product_3.name], # [shipment_2.created_on, shipment_2.completed_on, # user.name, product_2.name], # [shipment_1.created_on, shipment_1.completed_on, # user.name, product_1.name], # ] # end
  19. describe "ordering" do it "reorders shipments by their creation date"

    do shipment_1, shipment_2 report = described_class.new(user, [shipment_1, shipment_2]) result = report.data expect(result.map(&:first)).to eq( [shipment_2.created_on, shipment_1.created_on] ) end end
  20. Factory AR records AR queries create(:user) 1 10 create(:meal) 5

    41 create(:full_menu) 94 584 create(:weekly_basket) 104 644 create(:user, :with_order_history) 379 2336
  21. describe "ordering" do it "reorders shipments by their creation date"

    do shipment_1, shipment_2 report = described_class.new(user, [shipment_1, shipment_2]) result = report.data expect(result.map(&:first)).to eq( [shipment_2.created_on, shipment_1.created_on] ) end end
  22. let!(:shipment_1) { create(:shipment, product: product_1, created_at: 2.days.ago) } let!(:shipment_2) {

    create(:shipment, product: product_2, created_at: 3.days.ago) } let!(:shipment_3) { create(:shipment, product: product_3, created_at: 4.days.ago) } let!(:shipment_4) { create(:shipment, product: product_4, created_at: 5.days.ago) }
  23. let(:output_records) do [ [shipment_4.created_on, shipment_4.completed_on, user.name, product_4.name], [shipment_3.created_on, shipment_3.completed_on, user.name,

    product_3.name], [shipment_2.created_on, shipment_2.completed_on, user.name, product_2.name], [shipment_1.created_on, shipment_1.completed_on, user.name, product_1.name], ] end
  24. describe "ordering" do it "reorders shipments by their creation date"

    do old = create_shipment(date: 9.days.ago) new = create_shipment(date: 2.days.ago) report = described_class.new(user, [new, old]) result = report.data expect(result.map(&:first)).to eq( [old.created_on, new.created_on] ) end end
  25. # let(:product_1) { create(:product) } # let(:product_2) { create(:product) }

    # let(:product_3) { create(:product) } # let(:product_4) { create(:product) } # let!(:shipment_1) { create(:shipment, product: product_1, # created_at: 2.days.ago) } # let!(:shipment_2) { create(:shipment, product: product_2, # created_at: 3.days.ago) } # let!(:shipment_3) { create(:shipment, product: product_3, # created_at: 4.days.ago) } # let!(:shipment_4) { create(:shipment, product: product_4, # created_at: 5.days.ago) } # # let(:shipments) do # [ # shipment_1, # shipment_2, # shipment_3, # shipment_4 # ] # end # let(:output_records) do # [ # [shipment_4.created_on, shipment_4.completed_on, # user.name, product_4.name], # [shipment_3.created_on, shipment_3.completed_on, # user.name, product_3.name], # [shipment_2.created_on, shipment_2.completed_on, # user.name, product_2.name], # [shipment_1.created_on, shipment_1.completed_on, # user.name, product_1.name], # ] # end
  26. it "generates an output record for each input, sorted by

    date" do expect(csv_data).to eq(output_records) end
  27. it "generates an output record for each input, sorted by

    date" do expect(csv_data).to eq(output_records) end
  28. describe "ordering" do it "reorders shipments by their creation date"

    do old = create_shipment(date: 9.days.ago) new = create_shipment(date: 2.days.ago) report = described_class.new(user, [new, old]) result = report.data expect(result.map(&:first)).to eq( [old.created_on, new.created_on] ) end end
  29. it "serializes data as an array" do users = create_list(:user,

    3) response = subject.create(User.all).process response = response[0][4] expect(response).to eq(users.first.name) end
  30. it "serializes data as an array" do users = create_list(:user,

    3) serialized_users = subject.create(User.all).to_hashes response = serialized_users.first.full_name expect(response).to eq(users.first.name) end
  31. describe "ordering" do it "reorders shipments by their creation date"

    do old = create_shipment(date: 9.days.ago) new = create_shipment(date: 2.days.ago) report = described_class.new(user, [new, old]) result = report.data expect(result.map(&:first)).to eq( [old.created_on, new.created_on] ) end end
  32. describe "ordering" do it "reorders shipments by their creation date"

    do # Given old = create_shipment(date: 9.days.ago) new = create_shipment(date: 2.days.ago) # When report = described_class.new(user, [new, old]) result = report.data # Then expect(result.map(&:first)).to eq( [old.created_on, new.created_on] ) end end
  33. it "reorders shipments by their creation date" do old =

    create_shipment(date: 9.days.ago) new = create_shipment(date: 2.days.ago) report = described_class.new(user, [new, old]) expect(report.data.map(&:first)).to eq([old, new]) end
  34. it "returns order units summed, divided by units per shipper"

    do create_store_order(count_units: 4) create_store_order(count_units: 8) subject = described_class.new(store_orders: store_orders) total_shippers = subject.total_shipper_count expect(total_shippers).to eq(3) end
  35. it "returns a ceiling rounded value" do create_store_order(count_units: 7) subject

    = described_class.new(store_orders: store_orders) total_shippers = subject.total_shipper_count expect(total_shippers).to eq(2) end
  36. let!(:shipment_1) { create(:shipment, product: product_1, created_at: 2.days.ago) } let!(:shipment_2) {

    create(:shipment, product: product_2, created_at: 3.days.ago) } let!(:shipment_3) { create(:shipment, product: product_3, created_at: 4.days.ago) } let!(:shipment_4) { create(:shipment, product: product_4, created_at: 5.days.ago) }
  37. it "returns order units summed, divided by units per shipper"

    do create_store_order(count_units: 4) create_store_order(count_units: 8) subject = described_class.new(store_orders: store_orders) total_shippers = subject.total_shipper_count expect(total_shippers).to eq(3) end it "returns a ceiling rounded value" do create_store_order(count_units: 7) subject = described_class.new(store_orders: store_orders) total_shippers = subject.total_shipper_count expect(total_shippers).to eq(2) end
  38. describe "#total_shipper_count" do subject { described_class.new(store_orders: StoreOrder.all) } context "even

    division" do let!(:order1) { create_store_order(count_units: 4) } let!(:order2) { create_store_order(count_units: 8) } let(:expected_total) { 3 } it "returns order units summed, divided by units per shipper" do expect(subject.total_shipper_count).to eq(expected_total) end end end
  39. context "rounding" do let!(:order) { create_store_order(count_units: 7) } let(:expected_total) {

    2 } it "returns order units summed, divided by units per shipper" do expect(subject.total_shipper_count).to eq(expected_total) end end
  40. def user_summary(user) "(#{user.id}) #{user.full_name}, #{user.role}" end it "returns a user

    summary for printing" do user = User.new(id: 5, full_name: "Dave G", role: :admin) expected = "(#{user.id}) #{user.full_name}, #{user.role}" summary = user_summary(user) expect(summary).to eq(expected) end
  41. it "returns a user summary for printing" do user =

    User.new(id: 5, full_name: "Dave G", role: :admin) summary = user_summary(user) expect(summary).to eq("(5) Dave G, admin") end
  42. describe "#process" do it "return value" end describe "#process" do

    it "returns the number of records correctly persisted" end
  43. describe CreateShipmentHistoryReport do describe "#sorted_shipments" do it "returns an empty

    array when there are no shipments" end end be rspec ./spec/services/create_shipment_history_report_spec.rb —format=‘documentation’ # CreateShipmentHistoryReport#sorted_shipments returns an empty array when there are no shipments
  44. it “picks randomly, but correctly” do double1 = double double2

    = double result = [double1, double2].sample expect(result).to eq(double1) end # expected: #<Double (anonymous)> # got: #<Double (anonymous)>
  45. it “picks randomly, but correctly” do double1 = double("first record")

    double2 = double("second record”) result = [double1, double2].sample expect(result).to eq(double1) end # expected: #<Double "first record"> # got: #<Double "second record">
  46. it "checks result size" do arr = [1,2,3] response =

    arr.length expect(response > 3).to be_true end # expected true # got false
  47. it "checks result size" do arr = [1,2,3] response =

    arr.length expect(response).to be > 3 end # expected: > 3 # got: 3
  48. it "checks validity of a record" do thing = double(valid?:

    true) expect(thing.valid?).to be_false end # expected: false # got: true
  49. it "checks validity of a record" do thing = double("order",

    valid?: true) expect(thing).not_to be_valid end # expected `#<Double "order">.valid?` to return false, got true
  50. validate :failure_message, presence: true, if: :failed? it "sometimes requires failure_message"

    do job = JobLog.new(status: :failed) expect(job).to validate_presence_if(:failure_message) job = JobLog.new(status: :completed) expect(job).not_to validate_presence_if(:failure_message) end
  51. def user_summary(user) "(#{user.id}) #{user.full_name}, #{user.role}" end it "returns a user

    summary for printing, bad" do user = double(id: 5, full_name: "Dave G", role: :admin) response = user_summary(user) expect(response).to eq("(5) Dave G, admin") end
  52. it "returns a user summary for printing, better" do user

    = instance_double(User, id: 5, full_name: "Dave G", role: :admin) response = user_summary(user) expect(response).to eq("(5) Dave G, admin") end
  53. it "returns a user summary for printing, better" do user

    = User.new(id: 5, full_name: "Dave G", role: :admin) expect(user_summary(user)).to eq("(5) Dave G, admin") end
  54. 2. ACTUALLY, JUST DELETE THEM 3. TINY PIGS ARE WAY

    CUTER THAN CATS 1. KEEP YOUR TESTS MOIST
  55. 2. WRITE TESTS FOR HUMANS 3. TINY PIGS ARE WAY

    CUTER THAN CATS 1. USE TESTS TO DRIVE DESIGN