analytics-android icon indicating copy to clipboard operation
analytics-android copied to clipboard

Fake Implementation for Segment Analytics

Open saadfarooq opened this issue 3 years ago • 3 comments

Is there a way to Fake the Analytics object for tests? We prefer Faking to Mocking, but the Analytics object uses a builder and it's constructor takes a thousand parameters.

Would be nice if there was a module with a fake implementation to use for tests that allowed assertions on the values passed.

saadfarooq avatar Jun 30 '21 18:06 saadfarooq

Hi @saadfarooq! This is a great call :). Definitely seems like a great feature. Would you happen to have any resources / examples around this topic? I am unfamiliar with it so would love to grab some extra info here.

prayansh avatar Jun 30 '21 20:06 prayansh

Hey Prayansh,

So the semantic difference between mocks and fakes is that mocks test the implementation and fakes test the outcomes.

A mock would verify that our code called a method on it.

verify(mockAnalytics).track("someAction", Properties().apply { put(CATEGORY, "someCategory") })

A fake, on the other hand, would test if a value was received in some limited implementation.

fakeAnalytics.assertAction("someAction")
    .assertValue(CATEGORY, "someCategory")

The mock exposes the implementation details such as that the function is called track, but more importantly that it uses Properties object to bundle values so the tester needs to know if the Properties object supports value equality, for example.

The downside with fakes is that they usually have to be planned out and written, as opposed to mocks, which usually are taken care of by a mocking library.

Also, the design problem with writing fakes for you guys will be how to design the API, e.g. should it include assertions (and thus possibly an assertion library dependency) like RxJava's TestObserver or just provide values for users to assert like AndroidX's navigation testing. (Note: despite the naming these are basically fakes).

The main problem with the library right now is that the constructor takes too many parameters and also uses context. Otherwise, I would be able hack my way to a fake (by doing class FakeAnalytics: Analytics(mock(), mock()..... mock())) but because it uses SharedPreferences upon initialization, mocking context doesn't work and it seems too much to be stubbing that out in the mock.

Hope that was helpful.

saadfarooq avatar Jul 01 '21 00:07 saadfarooq

Hey @saadfarooq! thanks for the info (very helpful 😄 ). This does seem like an interesting feature. I will add it to our backlog, but I cannot promise any immediate progress, since we have other projects in flight currently.

I will update this issue once the status changes

prayansh avatar Jul 06 '21 20:07 prayansh