Dixie, turning chaos to your advantage.

Related tags

Testing Dixie
Overview

Dixie

Dixie

Dixie is an open source Objective-C testing framework for altering object behaviours. Test your app through creating chaos in the inner systems. The primary goal of Dixie is to provide a set of tools, which the developers can test their code with. Behind the goal is the ideology of "do not always expect the best". You can read more about this here.

Build Status

How can you test your application with Dixie

  1. Create a new target in your app’s project that runs your Dixie setup logic during app launch. With the separate target you can make sure all Dixie related code is separated and won’t be included in your production builds
  2. Change the behaviour of some components with Dixie and deploy the test build to device or simulator to see how your app behaves
  3. Once you got familiar with the library, it might be worth to create a list of behaviour changes that you can easily configure and combine from your debug build

A few ideas what you can do

  • Hijack the localisation component of your app to simulate long strings or other unexpected text
  • Inject mocked network responses into the network layer (you can match the URLs with a regular expression so you can provide different responses for different requests)
  • Network mocking can also be utilised in automated UI tests, so you don’t have to rely on real network communication
  • You can easily mock GPS coordinates or even the current date, so you do not have to set the simulators location manually
  • Inject randomised properties to your data models to see how robust is your application handling the objects received from web

In our projects we use Dixie in two ways

  1. We just put the Dixie configuration code in the AppDelegate and remove if not needed (these are short testing sessions). #ifdef-ing is an option, also creating a separate target that has a category on the AppDelegate.
  2. We use Dixie in the automated UI tests as a standard mocking framework. The tests rely on the final app target, and we found extremely hard to mock components on the low level (e.g. networking) in this scope.

Either way we think Dixie comes handy in cases, where you have to mock libraries, that's less configurable or some components are not that easily injectable.

Installation

With CocoaPods

CocoaPods is the recommended way to add Dixie to your project.

  • Add Dixie to your Podfile

    pod 'Dixie'

  • Install/update pod(s)

    pod install

  • Include DixieHeaders.h where you would like to use Dixie

    #import <DixieHeaders.h>

Without CocoaPods

You can add Dixie without CocoaPods to your project if you download the Dixie project and add it manually to your project. Don't forget to add the project path into the Header Search Path.

You can see an example for this integration in the Example app

##Usage First define which method on which class the change should be applied to, and its new behaviour. You can do this by creating a DixieProfileEntry:

//Tomorrow
NSDate* testDate = [NSDate dateWithTimeIntervalSinceNow:24*60*60];

//A behaviour to always return tomorrow's date
DixieChaosProvider* provider = [DixieConstantChaosProvider constant:testDate];

//Create the entry
DixieProfileEntry* entry = [DixieProfileEntry entry:[NSDate class] selector:@selector(date) chaosProvider:provider]

Then create an instance of a Dixie configuration, set the profile and apply.

//Create Dixie configuration
Dixie* dixie = [Dixie new];
	
//Set and apply change
dixie
	.Profile(entry)
	.Apply();

After applying the profile, every call of [NSDate date] will return the date for tomorrow instead of today. This way you can test date issues without going to the device settings and changing the date manually.

When you no longer need Dixie, revert your change:

//Revert the change of the entry
dixie
	.RevertIt(entry);

Full code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	NSDate* testDate = [NSDate dateWithTimeIntervalSinceNow:24*60*60];

	DixieChaosProvider* provider = [DixieConstantChaosProvider constant:testDate];
	
	DixieProfileEntry* entry = [DixieProfileEntry entry:[NSDate class] selector:@selector(date) chaosProvider:provider]
		
	Dixie* dixie = [Dixie new];

	dixie
		.Profile(entry)
		.Apply();
	
	return YES;	
}

You can set multiple profiles and also revert them all at once. You can also choose from some preset behaviours:

####DixieNonChaosProvider Provides the original behaviour. Good to use when you want to have a different behaviour in special cases only.

####DixieConstantChaosProvider Provides a behaviour that always returns a constant object.

####DixieNilChaosProvider Provides a behaviour that always returns nil.

####DixieBlockChaosProvider Provides a behaviour that is described by a block. Using this provider the method can be replaced with a full custom behaviour. For accessing method parameters and setting the return value you can use the DixieCallEnvironment object passed to the block.

####DixieRandomChaosProvider Provides a behaviour that returns a random object. The default implementation returns a random NSNumber.

####DixieExceptionChaosProvider Provides a behaviour that throws an exception.

####DixieSequentialChaosProvider For every call it returns the ith chaosprovider's behaviour, where i is the number of the call. If the number of calls exceeds the number of predefined chaosprovider the last provider's behaviour will be used.

####DixieCompositeChaosProvider Checks the parameters of the method and if one matches the value of a given DixieCompositeCondition, then it returns the connected chaosprovider's behaviour.

Under the hood

The idea of changing an object's behaviour is not new. It is usually used in unit testing, where a component's dependencies are mocked to have a controlled, reproducible environment. In these situations there is the requirement that the target project should be easily injectable. If you are depending on components that are not made by you, or that are not injectable, you have to turn to different methods. To implement the theory of creating chaos/altering component behaviour in Objective-C environment, Dixie uses the technique of Method Swizzling. Method swizzling relies on calling special runtime methods, that require knowing the target method and its environment. Dixie takes care of handling the runtime for you, and also hides the original method environment, so you only have to focus on defining the new behaviour and can apply it quickly and simply.

Note:

  • The current implementation is best at changing behaviours of methods on iOS simulator. Support for arm architectures will come in the next version.
  • Dixie is best for testing so, as with other similar libraries, its usage in production environments is strongly discouraged.

Example app

You can find a Dixie example app project in the repository with some common use-cases of how to use Dixie. The project requires CocoaPods dependency manager, so you have to run the pod install command in the DixieExampleApp directory before you can run the project.

The example app covers three use-cases:

Location mocking

Shows the actual location on a map using the CLLocationManager. Dixie changes the implementation of the locationManager:didUpdateLocations: method, so any location can be mocked easily. The example app mocks a random city. With Dixie Revert function the device location is used. The whole logic can be found in the MapViewController.m. It uses a DixieBlockChaosProvider to be able to change the method implementation with a block.

Date mocking

A countdown timer to the next Halley's Comet arrival. The countdown timer uses the actual date function ([NSDate date]) and Dixie changes the implementation of this method and mocks a random date between -10000 and +10000 days from the actual date. The whole logic can be found in the CountDownViewController.m. It uses a DixieConstantChaosProvider which provides a constant value mocking.

Network mocking

This example shows the weather at the actual location using OpenWeatherMap API as the data source and AFNetworking which is a popular iOS and OS X networking framework. Dixie changes the implementation of the GET:parameters:success:failure: method implementation of the AFHTTPRequestOperationManager class of the AFNetworking framework. The request is not going out to the network, Dixie creates the response object and calls the success callback which is the async callback coming from a successful network response. The whole logic can be found in the WeatherViewController.m, it uses a DixieBlockChaosProvider.

#About The Dixie was born from the idea of Peter Adam Wiesner. The prototype was brought to life by Phillip Wheatley, Tamas Flamich, Zsolt Varnai and Peter Adam Wiesner within a research lab project in one week. The prototype was developed into this open source library by Zsolt Varnai, Csaba Szabo, Zsombor Fuszenecker and Peter Adam Wiesner.

If you know a way to make Dixie better, please contribute!

You can reach us:

You might also like...
PlaygroundTester enables you to easily run tests for your iPad Playgrounds 4 project.

PlaygroundTester PlaygroundTester is a package that enables you to add tests to your iPad Swift Playgrounds project. Installation Just add PlaygroundT

BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.
BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.

BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.

An xcconfig (Xcode configuration) file for easily turning on a boatload of warnings in your project or its targets.

Warnings This is an xcconfig file to make it easy for you to turn on a large suite of useful warnings in your Xcode project. These warnings catch bugs

Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus.
Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus.

VPN On Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus. This App installs a Today Widget into Notificati

This project will add done button on TexField and TextViews by just turning on from storyboard.

RTDoneKeyboard Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation RTD

Visualize your dividend growth. DivRise tracks dividend prices of your stocks, gives you in-depth information about dividend paying stocks like the next dividend date and allows you to log your monthly dividend income.
Visualize your dividend growth. DivRise tracks dividend prices of your stocks, gives you in-depth information about dividend paying stocks like the next dividend date and allows you to log your monthly dividend income.

DivRise DivRise is an iOS app written in Pure SwiftUI that tracks dividend prices of your stocks, gives you in-depth information about dividend paying

Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.
Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.

Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.

Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!
Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!

OHHTTPStubs OHHTTPStubs is a library designed to stub your network requests very easily. It can help you: test your apps with fake network data (stubb

Automatically set your keyboard's backlight based on your Mac's ambient light sensor.
Automatically set your keyboard's backlight based on your Mac's ambient light sensor.

QMK Ambient Backlight Automatically set your keyboard's backlight based on your Mac's ambient light sensor. Compatibility macOS Big Sur or later, a Ma

Shows your current framerate (fps) in the status bar of your iOS app
Shows your current framerate (fps) in the status bar of your iOS app

WatchdogInspector Shows your current framerate (fps) in the status bar of your iOS app Be a good citizen! Don't block your main thread! WatchdogInspec

Get any text on your screen into your clipboard.
Get any text on your screen into your clipboard.

macOCR macOCR is a command line app that enables you to turn any text on your screen into text on your clipboard. When you envoke the ocr command, a "

A communication channel from your Mac to your watch.
A communication channel from your Mac to your watch.

Stargate A communication channel from your Mac to your watch. Providing a convenient wrapper around MMWormhole and PeerKit, Stargate leverages Multipe

Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur

Buildasaur Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running

Displays your HomeKit temperature sensors in your menu bar
Displays your HomeKit temperature sensors in your menu bar

Temperature Glance Displays your HomeKit temperature sensors in your menu bar Screenshot Note This is a very simple app that I made for myself but dec

SwiftUI Animation Library. Useful SwiftUI animations including Loading/progress, Looping, On-off, Enter, Exit, Fade, Spin and Background animations that you can directly implement in your next iOS application or project. The library also contains huge examples of spring animations such as Inertial Bounce, Shake, Twirl, Jelly, Jiggle, Rubber Band, Kitchen Sink and Wobble effects. Browse, find and download the animation that fits your needs. Pegase is a beautifully easy tool to keep track of your financial life on all your macOS
Pegase is a beautifully easy tool to keep track of your financial life on all your macOS

Pegase 🎉 Features 📒 Documentation Personal account software Pegase is a beautifully easy tool to keep track of your financial life on all your macOS

Application where you can build your portfolio with your Educations, Experiences, Projects, and Achievements
Application where you can build your portfolio with your Educations, Experiences, Projects, and Achievements

App Store Link Application where you can build your portfolio with your Educations, Experiences, Projects, and Achievements Description Signup with ne

Shows your photo library grouped by events, to easily export them to your computer
Shows your photo library grouped by events, to easily export them to your computer

Groupir Shows your photo library grouped by events, to easily export them to your computer Features Currently supported features: reading your photo l

Comments
  • Support for primitive return type method signatures

    Support for primitive return type method signatures

    Added support for most used primitive types:

    • Turned on original value storage
    • Created macro for different block wrapper implementation
    • Logger will only log objects (for now)
    • DixieCallEnvironment: using void* instead of id for returnValue
    • added unit tests for as many method variation as we could think of

    Fixed multiple parameter parsing problem:

    • passing va_list by reference (passing it by value copied the state and the parsing method read always the first element)

    Validated with the contribution guideline:

    • Updated read.me and Example app to support iOS9
    opened by WiesnerPeti 0
Releases(1.0)
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur

Buildasaur Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running

Buildasaurs 774 Dec 11, 2022
PinpointKit is an open-source iOS library in Swift that lets your testers and users send feedback with annotated screenshots using a simple gesture.

PinpointKit is an open-source iOS library in Swift that lets your testers and users send feedback with annotated screenshots using a simple gesture. F

Lickability 1.1k Jan 6, 2023
View your app on different device and font sizes

Sizes reduces the time it takes to evaluate all of our apps possible device sizes, orientations and font combinations. With Sizes we'll avoid launchin

Marcos Griselli 1.2k Oct 27, 2022
AutoMocker is a Swift framework that leverages the type system to let you easily create mocked instances of your data types.

AutoMocker Context AutoMocker is a Swift framework that leverages the type system to let you easily create mocked instances of your data types. Here's

Vincent Pradeilles 39 May 19, 2022
Mock Alamofire and URLSession requests without touching your code implementation

Mocker is a library written in Swift which makes it possible to mock data requests using a custom URLProtocol. Features Requirements Usage Activating

WeTransfer 898 Dec 26, 2022
Small library to easily run your tests directly within a Playground

[] (https://developer.apple.com/swift/) Build Status Branch Status master develop About PlaygroundTDD enables you to use TDD directly on Xcode Playgro

Whiskerz AB 317 Nov 22, 2022
Switchboard - easy and super light weight A/B testing for your mobile iPhone or android app. This mobile A/B testing framework allows you with minimal servers to run large amounts of mobile users.

Switchboard - easy A/B testing for your mobile app What it does Switchboard is a simple way to remote control your mobile application even after you'v

Keepsafe 287 Nov 19, 2022
Control your iPhone from inside Xcode for end-to-end testing.

Remote - Control your iPhone from Xcode "Remote" is a plugin for Xcode that allows you to control an iPhone from a window on your Mac during developme

John Holdsworth 791 Dec 26, 2022
Lightweight touch visualization library in Swift. A single line of code and visualize your touches!

TouchVisualizer is a lightweight pure Swift implementation for visualising touches on the screen. Features Works with just a single line of code! Supp

Morita Naoki 851 Dec 17, 2022
Freezer is a library that allows your Swift tests to travel through time by mocking NSDate class.

Freezer Freezer is a library that allows your Swift tests to travel through time by mocking NSDate class. Usage Once Freezer.start() has been invoked,

Sergey Petrov 8 Sep 24, 2022