Waterfall vs Agile

Leave a comment

I got a great question from someone taking my Udemy Agile Samurai Course about they merits of Waterfall and whether it could ever really work.

Here is the answer I wrote back.

Hi XXX – great questions.

Waterfall served us very well for over 40 years, and still continues to serve people well today. I travel and teach a lot all over the world. And I can tell you Waterfall is alive and well in places like Japan and India. But even in North America and Europe it is still used by many.

First let’s make one thing clear. Agile is no silver bullet. You can fail on an Agile project just like you can on any waterfall. The only difference is you will fail sooner (which for some is a good thing).

What’s made Agile rise in popularity over the last twenty years or so are several things:

1. Computers got faster.

We used to have to spend a lot of time getting everything right upfront, because the punch cards containing the code used to program early computers needed to be pretty much perfect. One wrong card and your program would fail. So we put in a lot more effort to get things right.

2. The cost of change dropped.

Related to this was the fact that day, we have ways of developing software that we could have only dreamed of 30 or 40 years ago. Just-in-time compilers. Databases on everyones desktop. Mobile phones. All of this would have been fantasy not so long ago.

But now the cost of change in re-programming these devices has radically dropped. We can deploy websites in mins and seconds. As opposed to the weeks and months it used to take. So we no longer need to get everything right up front. Now we can deploy and learn.

3. The speed of business has changed.

Business needs have forced us to come up with ways of adapting faster that Waterfall could handle. That and the fact that…

4. Our customers don’t always know what they want.

Means we need a way to allow our customers to change their mind as they develop the system. This is the radical departure from the past and the biggest difference between Agile and Waterfall. Waterfall pressures you do get everything right up front because it assumes the cost of change is hight. Today that is no longer true. The cost of change is low. Which means business can learn and discover what they true requirements really are as they develop the software.

This is scary. Especially for Waterfall folks who are so used to having to get everything right upfront.

If you are just beginning your Agile journey, my advice is to try Agile out on a small project, see how it goes, and start there. This is a cultural thing as much as a personal thing. Not all companies like or are ready for Agile because it really changes the way you and your teams need to work.

But it’s becoming more popular because business and realizing they now have less choice. And that if they can manage expectations in such a way that defines the success of a project as being more than on time and on budget, they get better results from their software efforts.

Great question. Good luck with your journey.

Jonathan

Advertisements

Crucial Conversation

Leave a comment

Screen Shot 2017-01-25 at 5.35.31 AM.png

 

Just had a day of Spotify training around Crucial Conversation. It’s actually being quite good.

It outlines a process around which how one can prepare for a crucial conversation one is about to have. The part I liked the most was how to prepare your message in three simple steps.

  1. State the facts.
  2. Say how this makes your feel.
  3. Ask the other person how they feel, and whether you are way off.

The key is to do this sincerely, from the hear, and to assume good intentions. If you do this, you stand a much better chance achieving the dialog you are looking for.

You may not always get what you want. But at least you’ll set the right conversation up for where ever it is you are going.

Good luck!

Screen Shot 2017-01-24 at 5.03.09 AM.png

Screen Shot 2017-01-24 at 5.03.27 AM.png

The Way of the Web Tester

Leave a comment

Screen Shot 2016-09-15 at 5.45.37 AM.png

Hello everyone. A book I have been working on diligently for the last two years has finally hit the shelves. It’s called The Way of the Web Tester and it’s a book for anyone who wants to learn how to write automated tests for the web.

What’s in this book?

The book starts out by explaining what the three kinds of tests are that we typically see in web projects, along with some rules of them and guidance on where and when to use each.

We they spend a full two chapters at each level of something called the testing pyramid seeing how to add UI tests to legacy systems, how one can test web services, along with some rules of thumb around unit testing. That’s Part I.

Screen Shot 2016-09-15 at 6.25.50 AM.png

In Part II we build on the concepts outlined in the testing pyramid, but shift our focus to those skills specifically geared towards writing good tests.

First we look at some of the basics of programming, and show how by learning a few simple principles and practices we can dramatically increase the readability and maintainability of our automated tests.

We then look at some practices around test organization, and see how by simply grouping and organizing our tests in certain ways can make maintaining our tests so much easier.

And in the chapter on effective mocking, we look at some of the perils that come with this style of unit testing, and see how we can use mocks effectively while staying out of the swamp of mocking.

And we conclude with a section on the art of writing tests first. And see how beginning with the end in mind not only helps you test your systems, it can actually help you iterate on your design.

Who is this book for?

Screen Shot 2016-09-15 at 6.52.26 AM.png

If you are a tester who’s always wanted to get into test automation, this is the perfect book for taking that first step into a larger world.

If you are a developer, and you’d like to learn how to make your code even more robust, this book will show you how to move fast without breaking stuff.

And if you are team lead, looking better ways to get your testers and developers together, his is the Rosetta Stone you’ve been looking for.

Once your team has a common framework, language and understanding around automated testing, they will be able to better coordinate they’ll their efforts and write the best automated tests for your project.

So wait no further. Crush bugs. Move fast. And have fun. I hope you enjoy The Way of the Web Tester.

On sale now at all reputable book stores.

https://pragprog.com/book/jrtest/the-way-of-the-web-tester

https://www.amazon.com/Way-Web-Tester-Beginners-Automating/dp/1680501836

 

Objective-C – How to stub out an NSError unit test

Leave a comment

#import <XCTest/XCTest.h>

#import "Player.h"

// Mocking somethings (like NSError's) can be tricky in OCMockito.
// One alternative, if your mocks get too complex, is to simply manually stub.

// create a test class for the behaviour your want to stub,
// override the methods
// and then inject that into your SUT

// For example

// Test class we want to stub
@interface FakeHandler : Handler
- (BOOL)playTrack:(NSString *)track error:(NSError **)errorPtr;
- (BOOL)playAlbum:(NSString *)album error:(NSError **)errorPtr;
@end

@implementation FakeHandler

// Method / behaviour we want to override
- (BOOL)playTrack:(NSString *)track error:(NSError **)errorPtr {

    NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
    NSString *desc = NSLocalizedString(@"Unable to connect to network.", @"");
    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };

    *errorPtr = [NSError errorWithDomain:domain
                                         code:-101
                                     userInfo:userInfo];

    return NO;
}

- (BOOL)playAlbum:(NSString *)album error:(NSError **)errorPtr {
    return NO;
}

@end


// Now we can use all of this in our test.

@interface PlayerStubTest : XCTestCase
@property (nonatomic, strong) Player *player;
@property (nonatomic, strong) Handler *fakeHandler;
@end

@implementation PlayerStubTest

- (void)setUp {
    [super setUp];
    self.fakeHandler = [FakeHandler new];
    self.player = [[Player alloc] initWithHandler:self.fakeHandler]; // Dependence inject our stub
}

- (void)testNetworkFailure {
    // Now when we call our play method, we can expect a failure and test that it bubbles up
    NSError *expectedError;
    [self.player playURL:@"track.xxx" error:&expectedError];
    XCTAssertNotNil(expectedError);
}

@end

How to throw and test exceptions in Objective-C

Leave a comment

PlayerTest.m

- (void)testInvalidUrl {
    XCTAssertThrows([self.player playURL:@"foobar" error:NULL], @"Invlaid url.");
}

Player.m

- (BOOL)playURL:(NSString *)url error:(NSError **)errorPtr {
    if ([url containsString:@"track"]) {
        return [self.handler playTrack:url error:errorPtr];
    } else if ([url containsString:@"album"]) {
        return [self.handler playAlbum:url error:errorPtr];
    } else {
        [NSException raise:@"Invalid url" format:@"%@ must be a track or an album.", url];
    }
    return NO;
}

Dealing with Errors in Objective-C

Leave a comment

A reminder to myself around where and when to use NSError vs throwing exception in Objective-C.

This article gives a nice summary

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/ErrorHandling/ErrorHandling.html

Use NSError for Most errors

When things go wrong in your app, due to

x network connectivity
x database been down etc

Use NSError and pass errors by reference.

- (BOOL)writeToURL:(NSURL *)aURL
 options:(NSDataWritingOptions)mask
 error:(NSError **)errorPtr;

Create an error pointer/reference and pass it to your method

NSError *anyError;
BOOL success = [receivedData writeToURL:someLocalFileURL options:0
 error:&anyError];

if (!success) {
 NSLog(@"Write failed with error: %@", anyError);
 // present error to user
}

The recover if possible and display an error to the user.

Generating your own errors

To create your own error define your own error domain.

com.companyName.appOrFrameworkName.ErrorDomain

Along with a unique error code for each error that may occur.

NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
 NSString *desc = NSLocalizedString(@"Unable to…", @"");
 NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };
 
 NSError *error = [NSError errorWithDomain:domain
 code:-101
 userInfo:userInfo];

Then use as follows

- (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr;

- (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr {
 ...
 // error occurred
 if (errorPtr) {
 *errorPtr = [NSError errorWithDomain:...
 code:...
 userInfo:...];
 }
 return NO;
}

Exceptions are Used for Programmer Errors

- (void)testInvalidUrl {
 XCTAssertThrows([self.player playURL:@"foobar" error:NULL], @"Invlaid url.");
}

- (BOOL)playURL:(NSString *)url error:(NSError **)errorPtr {
 if ([url containsString:@"track"]) {
 return [self.handler playTrack:url error:errorPtr];
 } else if ([url containsString:@"album"]) {
 return [self.handler playAlbum:url error:errorPtr];
 } else {
 [NSException raise:@"Invalid url" format:@"%@ must be a track or an album.", url];
 }
 return NO;
}

How to stub a class for unit testing

Leave a comment

Here is an example of how to override an existing class and create a stub for your unit tests in objective-c.

PlayerStubTest.m

#import <XCTest/XCTest.h>

#import "Player.h"
#import "Handler.h"

@interface PlayerStubTest : XCTestCase
@property (nonatomic, strong) Player *player;
@property (nonatomic, strong) Handler *stubHandler;
@end

// overide default behavior of handler for those methds you want to test
@interface StubHandler : Handler
- (BOOL)playTrack:(NSString *)track;
- (BOOL)playAlbum:(NSString *)album;
@end


@implementation StubHandler

- (BOOL)playTrack:(NSString *)track {
 NSLog(@"Stub track");
 return NO;
}

- (BOOL)playAlbum:(NSString *)album {
 NSLog(@"Stub albumn");
 return NO;
}

@end

@implementation PlayerStubTest

- (void)setUp {
 [super setUp];
 self.stubHandler = [StubHandler new];
 self.player = [[Player alloc] initWithHandler:self.stubHandler];
}

- (void)testExample {
 [self.player playURL:@"track"];
}

@end

 

When you run this you should see ‘Stub track’ in the console.

 

Older Entries

%d bloggers like this: