Record UI tests in Xcode

In a previous article I gave a short introduction into UI testing with Xcode. It works fine, but sometimes it’s a bit complicated to learn how to interact with the ui elements. This video shows by example how the recording feature helps with this problem.

Demo: Record UI interaction


Continue reading “Record UI tests in Xcode”

Are you a developer or do you just write code?

I am now about 10 years as self taught developer in business, and over the last years I learned the one thing: A good developer must know much more then just how write code!

When you just start out, the technology and the code itself are the most important thing. Learning a programming language and really master it by understanding complex concepts is really hard.
As a beginner, you know the frustration of compiler errors, crashing applications and weird problems of all kind. So often you stood before a mountain of problems and after some time and many tries – you will reach the top of the mountain. You jump up from your chair dancing and shouting Yes! Yes! finally! I got it!
This is a rewarding and motivates you to go on. In the best case you continue reading technical books and try to learn another language. You go on and solve more and more and more complex problems and projects. You hack the hell out of your editor and work long, long hours – you’re on the way to become an intermediate programmer. Some developers stop here. They don’t learn new things – only if they have to, and some even can’t program a fizz buzz game without google.

No matter of what kind you are, something strange happens with your projects – over and over again: A shiny new project begins on a green field with blue sky. As the development continues it start’s to rain and the ground becomes a bit muddy – no problem. Things just slow down a bit.
But then, yeah, then comes the day. The day of the meeting with the customer when you demonstrate the application and he says ok – this is good, but not that, what we exactly need! We would like things to go better this way, and by the way we also need this, and that… and you start to become stressed and angry. Why have they changed their mind? A few weeks and month ago we agreed on doing things as we’ve implemented them? Life goes on, requirements (and the business) change.
The time is running up and the way I developed the application, it will become extremely complicated to change it the meet the new requirements…
Time’s ticking and you start to hack around. The muddy field has become a stormy desert with lava rivers. You just want to survive.  After long days, nights and maybe weekends you feel burned out and are just happy that the project is over. Every requested additional feature is blocked “because changes are too complex” or “too dangerous”. Ongoing bugfixes and happy hours in the debugger are normal.

And again, some developers just accept this as the way it is. It’s always been like this in software development – so what. But others, especially those who continue to read and learn may become sceptical. This can’t be the way how software is developed!

So you’ll learn how to test the code. This is again a very, very hard thing. It sound’s simple, but testing your software and in best case adopting test driven development is hard, really hard. To test your code you have to make it testable. You are forced to learn how you decouple classes and how to apply the SOLID principles. Writing good test’s that don’t act like a house of cards and getting a feeling of how to test what – and what not – requires experience which you’ll gain only be doing it over and over again.

Also at some point you may stumble over agile software development. When you’ll try to adopt it, you’ll see that software development is not just about us – the developers. The agile way of development is absolutely different then the way you’ve done it before. Maybe you started with none or some conception or weeks / months of requirement capturing and planning.
As an agile developer the development lifecycle becomes faster. You strive to get working, high quality software to your customer. Good code quality and a safety net of test’s allow you to add features, that the customer wants in a steady pace. You’ll see the debugger only occasionally and yes, there are bugs, but much less. You automate what’s possible and build short feedback loops (Continuous Integration: Improving Software Quality and Reducing Risk (Martin Fowler Signature Books)
and Continuous Delivery: Reliable Software Releases Through Build, Test, and Deployment Automation (Addison-Wesley Signature)).

When you work agile another thing is also changing: You talk much more often with your project team, the stakeholder and / or the customer. Instead of reading large specification documents you learn what and why to implement something by talking with the customer. You have to learn to be come an effective communicator.

And also you’ll notice that you need to organise your work. Different types of work like business projects, internal projects, operational change and unplanned work. Phone-Calls, Mails, IM’s and other distractions all over the day.  Learn to manage your time, energy and the work. I personally use the Pomodoro Technique and Kanban.

Another thing you have to learn about is yourself: How your brain works and how you learn effectively. Andy Hunt wrote a great book about it: Pragmatic Thinking and Learning: Refactor Your Wetware (Pragmatic Programmers)

Our business is changing so fast, that everybody who don’t do this on a frequent base is falling behind and is risking to become totally outdated.
Don’t stick only to your everyday business, read and learn also about other languages and technologies.

A professional developer is curious and always learning. He is used to uncertainty and fear and comes over it by breaking tasks into small pieces just starts working in them. He makes changes also in very small steps. He knows about procrastination and about the imposter syndrome. He is aware, that clean and tested code is extremely important, because it makes software maintainable. And maintainability is in my opinion the most important aspect, more important then performance.

Those are some of the things, that I would say to myself if I could travel back in time. That would have made many things easier…. because this is not possible I’ll have to continue to learn from my failures. I want to stay a passionate developer!

XCode iOS UI testing

As Martin Flowler described in his article TestPyramid, the UI should be the highest (and not the only) layer of the tests.  They are a safety net and errors detected on this layer can point to missing test’s on a lower layer. Automated UI test’s tend to be brittle, because every change in the UI can result in failing test’s.

Since version 7 XCode supports UI tests, with test classes deriving from XCTestCase:

Here’s an example test:

class PersonalProductivityAssistantUITests : XCTestCase {
    
    var app = XCUIApplication()
    var toolbarAddActivityButton: XCUIElement?
    var activityInputField: XCUIElement?
    //...
    var timeLogSaveButton: XCUIElement?
    
    override func setUp() {
    	super.setUp()
    	
    	continueAfterFailure = false
     
    	app.launch()
    
    	activityInputField = app.textFields["textEditActivity"]
    	toolbarAddActivityButton = app.toolbars.buttons["Log Time"]
        // ...
    	timeLogSaveButton = app.navigationBars["Time Log"].buttons["Save"]
    }
    
    override func tearDown() {
    	super.tearDown()
    	
    	app.terminate()
    }
}
func testCanAddAndEditAndDeleteActivityFromTable() {
    //
    // Add
    //
    // Open the add time log view
    waitForElementToAppear(toolbarAddActivityButton!)
    toolbarAddActivityButton!.tap()
    toolbarAddActivityButton!.tap()
    
    // Type new time log informations
    waitForElementToAppear(activityInputField!)
    let initialActivityName = getActivityNameWithDateTime()
    typeActivityName(initialActivityName)
    labelActivity?.tap()
    
    buttonPickDateTimeFrom?.tap()
    setDatePickerValues(monthAndDay: "Aug 1", hour: "10", minute: "30", amPm: "AM")
    setDateTimeFromButton?.tap()
    
    buttonPickDateTimeUntil?.tap()
    setDatePickerValues(monthAndDay: "Aug 1", hour: "11", minute: "15", amPm: "AM")
    setDateTimeUntilButton?.tap()
    
    timeLogSaveButton?.tap()
    
    // Verify element has been added
    XCTAssert(getTableStaticTextElement(initialActivityName).exists)
    
    //
    // Edit
    //
    // tap the actiity to open the add/edit segue
    getTableStaticTextElement(initialActivityName).tap()
    
    let changedActivityName = "\(getActivityNameWithDateTime()) #test"
    waitForElementToAppear(activityInputField!)
    clearAndTypeActivityName(changedActivityName)
    
    timeLogSaveButton?.tap()
    
    // Verify element has been modifed
    XCTAssert(getTableStaticTextElement(changedActivityName).exists)
    
    //
    // Delete
    //
    // Swipe up until the new element ist visible
    doSwipeUpUntilTableStaticTextIsHittable(changedActivityName)
    // Swipe left and push delete button
    doDeleteTableRow(changedActivityName)
    
    // Verify the element has been deleted
    XCTAssert(!getTableStaticTextElement(changedActivityName).exists)
}

This is how it looks like, when it runs in the debugger:

You can find the full test in the latest version of my learning app PersonalProductivityAssistant @github.

Learn more about recording UI tests.