- Notifications
You must be signed in to change notification settings - Fork0
ndPPPhz/TruthTableOption
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
The TruthTableOption is a Swift protocol which helps both Devs and QAs on writing human-readable and easy editable tests.It's applicable anywhere you can synthesize your logic with aTable Of The Truth.
Imagine a scenario like the following one:You have to write and test a new feature which tells you whether you need to display a new banner containing a discount code to the users.You have been told from your business analyst that you only have to show the new banner in your app when:
- The customer gender is female
- Is a new customer or is the international women's day
After discussing with your QAs you end up with the following ACs
newCustomer | isInternationalWomensDay | isFemale | Result |
---|---|---|---|
false | false | false | false |
false | false | true | false |
false | true | false | false |
false | true | true | true |
true | false | false | false |
true | false | true | true |
true | true | false | false |
true | true | true | true |
Developing a feature like that, requires different layers of logic which have to be fully tested.Pretty sure you'd like to avoid writing single tests for each scenario. Moreover, in future, you should be able to extend this featurewithout trying to understand how the logic works.Debugging gets harder as big as the table and the requirement grows
This can be reduced to something like this:
and here's where the TruthTableOption comes to rescue.
- Create an enum which has a
String
as RawValue and conforms toTruthTableOption
. - Add a case for each column of the table.
- Implement
passingScenarios
in the following manner:- For each row where the result is true
.true
when the condition should be true.false
when the condition should be false.dontCare
when the condition could be bothtrue
orfalse
- For each row where the result is true
enumPromoBanner:String,TruthTableOption{staticvarpassingScenarios:[Set<TruthTableOptionDescriptor<PromoBanner>>]=[[.true(.isFemale),.true(.newCustomer)],[.true(.isFemale),.true(.isInternationalWomensDay)],[.true(.isFemale),.true(.newCustomer),.true(.isInternationalWomensDay)]]case newCustomercase isInternationalWomensDaycase isFemale}
Let's assume the following mock object
finalclassPromoBannerMock:PromoBannerInterface{var_isNewCustomer:Bool=falsevar_isInternationalWomensDay:Bool=falsevar_isFemale:Bool=falsevarisNewCustomer:Bool{return _isNewCustomer}varisInternationalWomensDay:Bool{return _isInternationalWomensDay}varisFemale:Bool{return _isFemale}}
and the following test
func testPromoBanner(){// Get the full table of truth and iterate for each rowforoptionRowinPromoBanner.fullOptionTable{// Set up the mock object with the current rowconfigureState(with: optionRow)testScenario(with: optionRow)}}privatefunc configureState(with optionRow:PromoBanner.Row){promoMock._isNewCustomer= optionRow.contains(.newCustomer)promoMock._isInternationalWomensDay= optionRow.contains(.isInternationalWomensDay)promoMock._isFemale= optionRow.contains(.isFemale)}privatefunc testScenario(with optionRow:MarioBonusLevel.Row){// The result from the managerletexpectedResult= manager.shouldShowBanner// The result from the table of the truthletresult= optionRow.resultXCTAssertEqual(result, expectedResult,"Expected result\(expectedResult) instead\(result)")}
If you are interested in the followed approach, take a look at
- Copyright 2018 © Annino De Petra
About
Swift protocol which helps both Devs and QAs on writing human-readable and easy editable tests using the logical table of truth
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.