The Object Inflation Test is a simple test to write and it can save you some serious headaches. Object Inflation Tests come in a couple of different flavors based on the kind of object you’re inflating. One way this test can come in handy is when you’re working with a model and a view. If your model defines the text you want to show in a UITableViewCell then you may want to write a test to ensure that that the UILabel s on your Cell contain the expected text from the model. Especially if you do any modification to the underlying data at the View or ViewModel layer (e.g. formatting currency).

Another flavor of the Object Inflation Test applies to deserializing JSON into your Model object. This is especially important to test because it can help you find issues early. If you’re not able to deserialize data or are deserializing it incompletely then that can lead to unexpected problems in other parts of your app.

The Object Inflation Test is just a test that you can fill a more complex object with data used for transport or storage.

Abstract representation of an Object Inflation Test

Test Case 1 – Woo Commerce

The Woo Commerce engineers wrote a test to check the that a given JSON string could could be parsed into an Account object. If you want to see the entire test you can check it out here.



Take a look at the following Code snippet from one of the Object Inflation Tests written for the Woo Commerce iOS App.

func testAccountFieldsArePropertlyParsed() { guard let account = mapLoadAccountResponse() else { XCTFail() return } XCTAssertEqual(account.displayName, "apiexamples") XCTAssertEqual(account.email, "example@example.blog") XCTAssertEqual(account.gravatarUrl, "https://1.gravatar.com/avatar/a2afb7b6c0e23e5d363d8612fb1bd5ad?s=96&d=identicon&r=G") XCTAssertEqual(account.userID, 78972699) XCTAssertEqual(account.username, "apiexamples") }

The function mapLoadAccountResponse() loads a blob of json that was saved locally called me.json and handles the mapping to the Swift object of type Account .

func mapLoadAccountResponse() -> Account? { guard let response = Loader.contentsOf("me") else { return nil } return try? AccountMapper().map(response: response) }

The actual json file used for the test is a little large so I cut out the values that were not mapped to the Swift Account object.

// me.json { "ID": 78972699, // 1 "display_name": "apiexamples", // 2 "username": "apiexamples", "email": "example@example.blog", ... "avatar_URL": "https:\/\/1.gravatar.com\/avatar\/a2afb7b6c0e23e5d363d8612fb1bd5ad?s=96&d=identicon&r=G", // 3 ... }

There are a couple of things here that make this mapping extra important to test.

It’s important to make sure that this JSON Number representation can be mapped to whatever specific numeric value type we’re using for our Swift model. The JSON key is display_name , but our Swift Model’s property name is displayName . We’ll want to make sure these values are associated properly even though the keys don’t match. We can use the convertFromSnakeCase decoding strategy to automate this conversion. The JSON key avatar_URL is completely different from the Account Model property it maps to: gravatarUrl . For this we’ll need to make sure the Account Model object implements the CodingKey protocol to map these keys together.

Test Case 2 – Eidolon (Artsy)

The following code sample, looks a little bit different because the tests were written with Quick and Nimble. That shouldn’t be a problem for you though even if you’re not familiar with those frameworks because the test it follows the standard format of a unit test with slightly different syntax.

For example, rather than a setup() function called before each test in an XCTestCase Nimble uses a beforeEach closure. These beforeEach closures can also be nested within tests. So For the test we’re looking at there are actually two beforeEach blocks

beforeEach { subject = PlaceBidViewController.instantiateFromStoryboard(fulfillmentStoryboard).wrapInFulfillmentNav() as! PlaceBidViewController subject.buyersPremium = { nil } } ... beforeEach { nav = FulfillmentNavigationController(rootViewController:subject) // 1 nav.auctionID = testAuctionID let artwork = Artwork.fromJSON(artworkJSON) let saleArtwork = SaleArtwork(id: "", artwork: artwork, currencySymbol: "£") saleArtwork.minimumNextBidCents = 25000 // 2 saleArtwork.openingBidCents = 10000 // 2 saleArtwork.highestBidCents = 20000 // 2 saleArtwork.bidCount = 1 // 2 nav.bidDetails = BidDetails(saleArtwork: saleArtwork, paddleNumber: nil, bidderPIN: nil, bidAmountCents: nil, auctionID: testAuctionID) }

Notice that the subject variable of this test is the rootViewController of the FulfillmentNavigationController which gets assigned to the nav variable. Next, notice that the setup to the test sets some of the properties of the saleArtwork model directly. This is done in order to prepare the model to render the view we want to test.

it("assigns correct text") { subject.loadViewProgrammatically() expect(subject.currentBidTitleLabel.text).to(equal("Current Bid:")) expect(subject.currentBidAmountLabel.text).to(equal("£200")) // 1 expect(subject.nextBidAmountLabel.text).to(equal("Enter £250 or more")) // 2 }

If you look at the above test you’ll see that the test checks that the text assigned to different UILabels has been slightly modified or (inflated) based on the values passed from the SaleArtwork model.

SaleArtwork has a currencySymbol property that has been set to the “£” sign. The test ensures that the currentBidAmountLabel.text value contains this sign. Additionally, the test checks that the saleArtwork.highestBidCents value has been properly formatted so the label shows the result of (20000 / 100) = £200. saleArtwork.minimumNextBidCents = 25000 sets the minimum for the next bid. This value should be formatted into the nextBidAmountLabel to match “Enter £250 or more”.

When To Use This Test?

As you’ve seen here, the Object Inflation Test can be useful in a number of different circumstances to confirm that your data has transformed properly. If you have models being sent back and forth to another system via an API then you should be testing that you can decode models in the format that they are being sent to your app. There is a problem with one of the presuppositions of the Woo Commerce test though, and that is that the static me.json text file represents an API response that could easily change. That doesn’t make the test not worth writing though! It just means that there is an additional layer that needs to be tested or there needs to be a system in place to confirm the contract between the Woo Commerce iOS app and the backend system that it interacts with.

As we’ve seen in the Artsy test there is also a good case to be made for writing Object Inflation Tests whenever you are using a Model to inflate a View. Even if the View is directly mapping values from the Model to objects on the View without any transformation it would be useful to confirm that these values were successfully mapped to the expected objects. This could possibly be replaced with Snapshot Tests (which we’ll talk about soon), but if you have the time then writing both tests would give you better coverage to confirm your app is working as expected.

Which Apps Use Object Inflation Testing?

Firefox ✅

WooCommerce ✅

Artsy ✅

Duck Duck Go ✅