Skip to content

Commit 955cb9f

Browse files
committed
Better expectation diffs in tests
1 parent 5fa4270 commit 955cb9f

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

spec/ios_send_app_size_metrics_spec.rb

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,46 +43,65 @@
4343

4444
# A test double to mock the Gzip compression and keep the 'fake-compressed' result readable in test failures
4545
class GzipWriterDouble < StringIO
46+
GZIP_PREFIX = '$GZIP$:'.freeze
4647
def close
4748
super
48-
self # `GzipWriter#close` returns `self` after closing (allowing method chaining), unlike default `StringIO#close`
49+
# `GzipWriter#close` returns `self` after closing (allowing use to use method chaining), unlike `StringIO#close`
50+
self
4951
end
5052

5153
def string
52-
"GZIP<#{super}>"
54+
"#{GZIP_PREFIX}#{super}"
5355
end
5456
end
5557

5658
describe Fastlane::Actions::IosSendAppSizeMetricsAction do
5759
let(:test_data_dir) { File.join(File.dirname(__FILE__), 'test-data', 'app_size_metrics') }
60+
let(:mocked_endpoint) { 'https://localhost/api/metrics' }
61+
let(:mocked_token) { 'token/1' }
62+
63+
# Utility method to turn a minified JSON into a pretty-formatted JSON (without the GZIP fake prefix if any)
64+
# To make any test failure and diff easier to debug
65+
def pretty_json(json_string)
66+
JSON.pretty_generate(JSON.parse(json_string.delete_prefix(GzipWriterDouble::GZIP_PREFIX)))
67+
end
5868

5969
def test_app_size_action(fake_ipa_size:, expected_json:, **other_action_args)
60-
mocked_endpoint = 'https://localhost/api/metrics'
6170
in_tmp_dir do |tmp_dir|
71+
# Arrange: Generate a fake `.ipa` file with the expected size
6272
ipa_path = File.join(tmp_dir, 'fake.ipa')
6373
File.write(ipa_path, SecureRandom.random_bytes(fake_ipa_size))
74+
75+
# Arrange: Mock GzipWriter with a mock for easier debugging in case of test failures
6476
allow(Zlib::GzipWriter).to receive(:new).and_return(GzipWriterDouble.new)
6577

78+
# Arrange: Stub any request to the mocked_endpoint, and memorize the received body
6679
expected_headers = {
67-
Authorization: 'Bearer token/1',
80+
Authorization: "Bearer #{mocked_token}",
6881
'Content-Type': 'application/json',
6982
'Content-Encoding': 'gzip'
7083
}
84+
last_received_body = nil
85+
stub = stub_request(:post, mocked_endpoint).with(headers: expected_headers) do |req|
86+
last_received_body = req.body
87+
end.to_return(status: 200)
7188

72-
stub = stub_request(:post, mocked_endpoint).with(
73-
headers: expected_headers,
74-
body: "GZIP<#{expected_json}>"
75-
).to_return(status: 200)
76-
89+
# Act
7790
code = run_described_fastlane_action(
7891
api_base_url: mocked_endpoint,
79-
api_token: 'token/1',
92+
api_token: mocked_token,
8093
ipa_path: ipa_path,
8194
**other_action_args
8295
)
8396

97+
# Asserts
8498
expect(stub).to have_been_made.once
8599
expect(code).to eq(200)
100+
expect(last_received_body).to start_with(GzipWriterDouble::GZIP_PREFIX), 'Payload is expected to be GZipped, but was not'
101+
# Compare the payloads as pretty-formatted JSON, to make the diff in test failures more readable if one happen
102+
expect(pretty_json(last_received_body)).to eq(pretty_json(expected_json)), 'Decompressed JSON payload was not as expected'
103+
# Compare the payloads as raw strings as a final check
104+
expect(last_received_body).to eq(GzipWriterDouble.new(expected_json).string)
86105
end
87106
end
88107

0 commit comments

Comments
 (0)