Tuesday, October 18, 2016

Setting up a Continuous Rails 5 TDD Feedback Loop with RSpec


As part of a red-green-refactor cycle, I appreciate a smooth, fast feedback loop. The slower the loop; the more my attention gets to another shiny object and my concentration gets broken. This tutorial aims to help you achieve a smooth red-green-refactor loop.

By the end you should be able to:

  • Setup testing frameworks:
    • RSpec, Shoulda-Matchers, Database Cleaner, Capybara, Factory_girl_rails, Faker
  • Write a Model test
  • Improve TDD Feedback loop using Guard and Spring
  • Setup Notifications

Setup App

rails new exampleapp -T (-T does not generate test files)

Setup Testing Frameworks

Update the Gemfile Include the following gems in your Gemfile:

group :development, :test do
  gem 'rspec-rails', '~> 3.4'
  gem 'factory_girl_rails', '~> 4.5'
  gem 'capybara', '~> 2.5'
group :test do
  gem 'shoulda-matchers', '~> 3.0', require: false
  gem 'database_cleaner', '~> 1.5'
  gem 'faker', '~> 1.6.1'

Run bundle install

Note: If you have any problems installing gems, primarily NokoGiri, run the following commands:

xcode-select --install
bundle install

Setup RSpec

rails generate rspec:install

The install will generate a spec directory and some skeleton files, including a .rspec file, which will be used later.


Shoulda-Matchers provide one line matchers for RSpec. We need to configure shoulda-matchers to work with RSpec by modifying the spec/rails_helper.rb file to include the following code snippet:

require 'rspec/rails'
require 'shoulda/matchers'
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails

Setup Database Cleaner

To setup database_cleaner, make the following modifications to spec/rails_helper.rb. Once complete, database_cleaner will clean the database between each unit test and each test suite.

config.use_transactional_fixtures = false

Make a new directory called support inside of your spec directory:

mkdir spec/support

Inside the new support directory, create a new file called database_cleaner.rb and paste in the following:

RSpec.configure do |config|
  config.before(:suite) do
  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  config.before(:each) do
  config.after(:each) do

Allow Rails to run this support file in it's setup. In rails_helper.rb, un-comment the following line:

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

Setup Capybara

Since we've already got the Capybara gem installed, just add the following line to the top of spec_helper.rb file:

require 'capybara/rspec'

Setup Faker and Factory Girl

Faker gem generates random data for testing. We will use this with factory_girl_rails in making a factory. To integrate FactoryGirl with RSpec, add the following line in rails_helper.rb within the RSpec.configure block:

config.include FactoryGirl::Syntax::Methods

Create a factory

Create a directory named factories in your spec folder. In the factories directory, create a file named after your model. Ex. ideas.rb

FactoryGirl.define do
  factory :idea do
    title       { Faker::Lorem.words(4) }
    description { Faker::Hacker.say_something_smart }

This factory allows you to generate fake data based on data generated by Faker to be used by FactoryGirl in running our tests.

Let's write a test!

Now that we have our testing frameworks in place, let's write our first Model spec!

Create a file in your model/spec folder for your model:

require 'rails_helper'
RSpec.describe Idea, type: :model do
  it "has a valid factory" do
    idea = build(:idea)
    expect(idea).to be_valid

Let's run the test from the terminal:

rspec spec/models/idea_spec.rb

This test will fail because we don't have an idea model. Let's create it!

rails g model Idea title:string description:string

This will want to overwrite the idea_spec.rb file and the spec/factories/ideas.rb file. Don't allow it, just enter 'n' for both. Then run:

rails db:migrate

Once the database has been migrated, lets run our test again.

rspec spec/models/idea_spec.rb


That feedback was good but it was a bit slow. Let's speed it up and gain more convenient feedback.

Improve TDD Feedback loop

Add the the following gems to your Gemfile:

group :development do
  gem 'guard-rspec', require: false
  gem 'spring-commands-rspec'
bundle install

Guard Setup

Guard is a neat gem that works with RSpec that watches your file system for changes and runs your test suite automatically. We need to initialize it, then we can run it

bundle exec guard init rspec
bundle exec guard

Spring Setup

Spring is new to Rails 5. This will setup our configuration once and then run tests repeatedly without having all the extra configuration overhead between each run. If you change rails configuration, you will need to restart the Spring.

For just one single test, this shaved a solid 5 seconds off of each test run!

spring binstub --all

Now, let's notify Guard to use Spring when running specs. In the Guardfile, modify the following line from:

guard :rspec, cmd: "bundle exec rspec" do


guard :rspec, cmd: "bin/rspec", all_on_start: true do

Then run guard:

bundle exec guard

There should be a line in the output that says "Running via Spring preloader in process..." From your idea_spec.rb file, trigger a save. You'll see in the terminal that it will automatically run the tests and not have to preload rails.

Ah, much faster feedback but keeping the terminal window open is kind of a drag. Let's fix that!


Let's provide notification pop ups whenever tests are run. This will allow us to keep the terminal window in the background and not have to even look at it unless we have test failures! Keeping our focus in the code requires less context switching and it's easy to setup!

I'm going to assume that you have a Mac and have brew installed. Install terminal-notifier

brew install terminal-notifier

Then, in your Gemfile, add the following gem:

group :development do
  gem 'terminal-notifier-guard', '~> 1.6.1'
bundle install

The last step is integrate terminal_notifier with guard. In your Guardfile, add the following line at the end of the file:

notification :terminal_notifier

Restart Guard if you had it running. After Guard runs your tests, you should receive a notification in the upper right hand corner saying all your tests passed!

Congrats! This TDD flow has helped me stay focus on the problem at hand and not worry about constantly checking the terminal, waiting for tests to run.

Thursday, July 7, 2016

Mock Server

Sometimes you need to mock out a web endpoint and Mock Server is a good tool to do this. There are many common uses cases for this including:
  • Working in conjunction with a 3rd party and the endpoint isn’t ready yet
  • Endpoint may not be reliable
  • Testing purposes
The advantages I saw of Mock Server versus others I looked at were:
  • Ability to register endpoints dynamically
  • Ruby library - Relatively simple to setup


Mock Server has two parts:
  • The Server - which can be downloaded from here as a jar
  • The client, which is available in Java, JavaScript, and Ruby. For this post, I’m going to focus on the Ruby gem.

Starting up Server

Run the following from the command line:
java -jar <path to mockserver-netty-3.10.4-jar-with-dependencies.jar> --serverPort 8080

Setup the client

Create a Gemfile and add the following:

gem ruby source: 'http://rubygems.org'
gem 'mockserver-client' 

Run bundle install

Create Expectations

Now that we are setup, in order to setup a mocked endpoint, an expectation needs to be created and registered with the Mock Server. Let’s setup a simple ‘GET’ endpoint for illustration.

Get Expectation

First, we’ll setup a class called ExpecationGenerator:
require 'mockserver-client'

class ExpectationGenerator
  include MockServer
  include MockServer::Model::DSL

  def initialize(server_port)
    @client = MockServerClient.new('localhost', server_port)

  def simple_get_expectation
    expectation = expectation do |expectation|
      expectation.request do |request|
        request.method = 'GET'
        request.path = '/simple-get'

      expectation.response do |response|
        response.status_code = 200
        response.body = "Success"

    expectation.times = unlimited() #once()

mock_server = ExpectationGenerator.new(8080)

Code highlights:
  • Setup a class that includes MockServer and the MockServer::Model::DSL
  • Initialize a MockServerClient with the server and port of where your mock server is running
  • Setup the expectation request and response for a ‘GET’ method
    • request.method can be set to ‘GET’, ‘POST’, etc.
    • request.path is the path to mock out
    • response.status_code returns the HTTP status code of the mocked method
    • response.body returns the body to be returned by the endpoint
      • expectation.times can be set to unlimited, as in our example. It can also be set to once(), twice(), etc. Once this endpoint gets hit n number of times, then it becomes invalid and will result in a 404.
  • last piece is registering the endpoint with the client
  • Now that we have the class setup, we need to instantiate it with the mock_server variable

Running the example

  • Start the mock server:
    • java -jar <path to mockserver-netty-3.10.4-jar-with-dependencies.jar> --serverPort 8080
  • Call the expectations.rb file
    • ruby expectations.rb

Prove that it works

  • Open up a browser, type in http://localhost:8080/simple-get and it should return “Success”
This post serves as an introduction to mock server. It’s capable of much more. I would encourage checking out Mock Server

Monday, May 16, 2016

5 Characteristics of a Great Product Owner

The Product Owner is a crucial part of the agile team.  I've had the experience of working with a number of different Product Owners.  This role is critical in leading the team in prioritizing work and having a vision for the product and knowing what to build.  Here are 5 characteristics I've observed in great Product Owners:

Trustworthy Partner

Trust is the number one characteristic of a making a great team.  The team that can trust each other can go far.  The Product Owner plays a crucial part in this.  This person needs to be able to trust the team to identify things they need and also for the team to speak up if there's issues/risks along the way.

A great PO will work through issues and partner with the team to come up with alternative solutions.  If a feature is much more effort than originally thought, is there an easier way we can get similar functionality, with less cost, that would still enable a useful user experience?  Being willing to negotiate and partner with the team to ensure the simplest, most cost effective solutions are being created.

This partnership means being actively participating in the scrum ceremonies: prioritizing stories, stand up, and retrospectives but constantly being available, ideally in the team room.  Team members may not constantly have questions to ask but recognize that once they do have questions, often times they are blockers until they get answers.  Blockers are expensive.  Having that conversation and answering questions sooner than later, keeps the team moving and delivering value.


A great PO has the power to make decisions.  He/she has autonomy to make decisions regarding the product.  The PO is the product ambassador, being tuned to the goals and users of this software solution and must be trusted from outside the team room to make decisions.  The more powerless the PO, the greater the time to market.


A great PO is experiencing pain.  If pain is not being experienced, what value is the software?  Pain tends to be a motivator to get things done.  A mix of power and pain can really be an asset to an agile team who strives to deliver value quickly and iteratively.

Product Focused

A great PO has the product's best interest in mind.  He/she is product driven, a solid idea of what the team needs to build, and what value each story has and prioritizes according to the biggest value first.  While they are a critical role in the process both inside and outside the team, the product is of first importance.

Political Prowess

Navigating the corporate landscape and getting things done fast on behalf of the team.  If the team needs a tool to make them faster or needs approval, the Product Owner knows how to navigate and get that tool or approval fast so the team can keep moving and delivering value at an optimum pace.

In your experience, what makes a great Product Owner?

Tuesday, January 13, 2015

Agile Retrospective Example: One Word and 4Ls

We had been doing your typical What went well/What didn't go well exercise and decided to change it up to hopefully gain some fresh ideas. We had a large team, roughly 20 people. I facilitated a retrospective and decided to change things up a bit and did 2 exercises: One word and the 4L's.

"Ice Breaker" - One Word (~10 min)

First exercise was to have everyone describe the sprint using one word. They were instructed that they didn't have to explain or expound on the word but the word could not be repeated. Everyone had to participate. As words were being shouted out, I would write them on the whiteboard. As it became quieter, I would call out for words from people who hadn't participated yet. This encourages the quieter ones to speak up early in the meeting and therefore have a greater chance of contributing later on now that they have "skin in the game".

"Main Event" (~50 min) - 4 L's

We called the categories:
  • Liked - things that went well during the sprint and we should continue to do 
  • Learned - things that we learned mid-sprint or things that didn't go well but we've learned from them 
  • Loathed - things that didn't go well 
  • Longs For - things that doesn't currently happen but would be "ideal". This topic is an exploration of ideas that could make the team better. Think no constraints. If the team could have anything they wanted, what would they ask for? 
  50 minutes

  Post-it notes, flip chart paper

  1. Everyone filled out post-it notes that pertained to each of the 4 categories (10 min)
  2. People placed them on one of the four flip chart pieces of paper (5 min)
  3. Assign people to one of the four groups to discuss (10 min)
  4. Discuss each topic, as an entire group, to glean ideas/action items (5 min/group - 20 min) 
  5. Review action items (5 min) 

Retrospective on the Retrospective: 

We had our retrospective in the team space. Often times, people would still be on their computers, working, during retrospective. We needed something to get them more engaged. The ice breaker was new we had done and it went well. Encouraging people to get engaged early on and getting the "quiet" ones to participate with one word was a simple exercise. These people, I noticed, were participating in the 4L discussion more than I had seen them contribute in the past. It's amazing what one word feedback will give you! After a few words, you would get a feel for how the sprint went, in just a few short minutes.

In order to encourage more engaging participation, I placed the four pieces of flip chart paper in the four corners of the room and instructed people to stand and discuss their topic. While they discussed, I walked around, checking in, and asked probing questions such as "How can we change this for next sprint?" or "This worked well during this sprint, how do we keep this going?". We did a divide and conquer. The goal of each group was to come up with the top 1 or 2 topics to discuss with the group as a whole and glean action items.

For time's sake, I had pre-determined groups of people to talk about certain categories. While this worked well, some people didn't like the topic they were assigned to. Ideally, if the retrospective were longer, I'd take each team spend some amount of time on each topic. That would take longer than an hour so we limited it to one topic per team.

We did get some valuable feedback from this retrospective. I believe, in part, because we changed up the way we gathered it. Too often, I think our retrospectives become too routine and, thereby, diluting the valuable feedback on how to improve. By keeping retrospectives fresh, it will encourage fresh ideas on how the team can improve.

Happy retrospecting!

Tuesday, October 22, 2013

Cross Browser/Cross Platform Automated Testing with Ruby

As developers, we’ve typically developed cross browser applications but now, with the advent of mobile devices, there’s a new plethora of devices to develop against.  How do we test against these? 
Cucumber + Watir-WebDriver + Appium = Cross Browser, Cross Platform Testing
We’ll walk through the highlights of setting up each browser and platform and also to capture screenshots.
The full code is available from my Github:  https://github.com/matthewbussa/watir-webdriver-demo
In order to start with, you’ll need the following software:
  • Ruby 1.9.3
    • Cucumber gem
    • Watir-WebDriver gem
  • Appium – please note that support for Appium in Windows is in “beta”
  • XCode
    • Install the Command Line tools (XCode –> Preferences –> Downloads –> Command Line Tools
    • Install the 6.1 Simulator in the same place
  • GenyMotion – free account is required.  Ensure you have Oracle VirtualBox installed before installing Genymotion

Cucumber Scenario to test:

Scenario: "Capture screenshot for one device and platform"
    Given I am on the home page
    Then a screenshot is captured

Setting up the Browser

With Watir-WebDriver it’s easy to setup in instance of a Watir Browser and initiate it for different browsers or platforms.  Below are some examples on how to utilize this feature:


    browser = Watir::Browser.new :firefox


For Chrome, you’ll need to download ChromeDriver v2.2  and place it in your class path.  Be sure to start the chromedriver before running your tests.  At the time of this writing, ChromeDriver v2.3 was not compatible.  The following is the Ruby code to setup an automated Chrome browser: 
    browser = Watir::Browser.new :chrome

For iPhone, iPad, and Android, ensure that Appium is up and running on the default port of 4723.  Appium will automatically load the iPhone and iPad devices however, it doesn’t automatically shut them down.  This can easily be done using the “kill ‘iPhone Simulator’” or kill ‘iPad Simulator’ commands from the terminal.


    capabilities = 
        'device' => "iPhone Simulator",
        'browserName' => 'iOS',
        'platform' => 'Mac',
        'version' => '6.1',
        'app' => 'safari'

    server_url = "http://localhost:4723/wd/hub/"
    driver = Selenium::WebDriver.for(:remote,
                 :desired_capabilities => capabilities,
                 :url => server_url)
    browser = Watir::Browser.new driver



The iPad version is the same as the iPhone setup with the exception that the ‘device” capability is different. 
    capabilities = 
        'device' => "iPad Simulator",
        'browserName' => 'iOS',
        'platform' => 'Mac',
        'version' => '6.1',
        'app' => 'safari'

    server_url = "http://localhost:4723/wd/hub/"
    driver = Selenium::WebDriver.for(:remote, 
                 :desired_capabilities => capabilities, 
                 :url => server_url)
    browser = Watir::Browser.new driver



In order for Android to work, ensure you have both Appium running and that you have an Android Emulator up using Genymotion. Also ensure that the Android Emulator you are using has the Chrome browser installed. This can be installed through the emulator's play store. A Gmail account will be needed to log into the Play Store.
  capabilities =
  'app' => 'chrome',
  'device' => 'Android'

  server_url = "http://localhost:4723/wd/hub/"
  driver = Selenium::WebDriver.for(:remote, 
               :desired_capabilities => capabilities, 
               :url => server_url)
  browser = Watir::Browser.new driver
  browser.driver.manage.timeouts.implicit_wait = 30


Capturing the Screenshot

The logic to capture a screenshot is fairly straightforward for non-Android devices.  However, Android devices are a bit tricky.  We need to save the screenshot to the sdcard on the emulator, then move the file to our location and finally, do some cleanup and delete the image on the sdcard.

def capture_screenshot()
  time = Time.now.to_i.to_s
  filename = time + '.png'
  if (platform == 'android')
    %x(adb shell /system/bin/screencap -p /sdcard/screenshot.png)
    %x(adb pull /sdcard/screenshot.png ./screenshots/screenshot.png)
    FileUtils.mv('./screenshots/screenshot.png', filename)
    %x(adb shell rm /sdcard/screenshot.png)
    browser.driver.save_screenshot filename


If you’re already using Cucumber and Watir-WebDriver for your automated web testing, Appium makes it easy extend your coverage utilizing the existing tool set and begin testing on mobile devices and if you’re not, here’s a framework to get you started!

Happy Testing!

Update 11/11/2013:  With the XCode 5.0, Apple removed the ability to launch built in applications.  This means that if you use XCode 5.0 or above, Appium will not launch Mobile safari, which is what the tests are setup to do.

No fear, the solution is to ensure you have XCode 4.6.3 and iOS Simulator 6.1.  You can download the older version here:  https://developer.apple.com/downloads/index.action#

There's some documentation on how to switch between versions of XCode from Appium here:  https://github.com/appium/appium/blob/master/docs/running-on-osx.md

Saturday, August 17, 2013

My First Advocare 24 Day Challenge Experience

My wife and I started the 24 day challenge on July 8. Our motivation for going down this journey was primarily for our boy/girl twins. To sweeten the pot a bit, we both also signed up for healthywage.com for longer term motivation. We are both obese and wanted to form healthier habits in order to gain more energy but most of all to maintain these healthier habits so when the twins get to the point of eating solids, we can teach them good habits in hopes they won't have the same struggles as we have had. We didn't want a diet, we wanted a lifestyle! After hearing multiple friends having great success with Advocare, we decided to try it.

Before Advocare 

I was a frequent fast food/restaurant shopper. I'd often go to McDonalds for breakfast, go out for lunch, then have dinner at home and snack in between. I did more than my share of mindless eating and snacking. I would go out to lunch most days at work mostly because everyone else was doing it and not really eating healthy. Never really paid attention to what was going into my mouth. We don't have control over a lot of things in our lives but we do have control over what goes into our mouths!

A day before we started Advocare, we decided we would have somewhat of a "last meal". Mine was Skyline Chili. Yum!

Then we started...

Days 1-10 

First day of Advocare, we started the morning with the Spark (Grape and Fruit Punch are my favorites) and followed up with the Fiber Drink and necessary pills. The Fiber Drink was disgusting, tasted like pulpy cardboard! You need to drink this fast else it turns to a thick slush. The taste is somewhat improved if you mix it with the Mandarin Orange Spark, tastes more like orangey, pulpy cardboard.

The first few days I had very bad headaches, primarily in the evenings. For me, I think it was somewhat of sugar withdrawl but also I would skip eating snacks primarily because I was working and couldn't work it in. I ended up taking headache medicine the first few days to help calm them down. I was forced to work the snacks in at work. Over time, eating snacks did get somewhat better. I would at least eat one snack per day (you should eat 2) but not optimal.

We made meal changes like wrapping lettuce in turkey burgers instead of having hamburgers with cheese and a bun. It is a change but I didn't miss the bread or cheese nearly as much as I thought I would!

After the first couple days, the challenge became more routine. We really watched we ate and became more mindful of the food decisions we were making. I quit going out to eat cold turkey. It's amazing how much money you spend going out to eat and how much more money you have when you stop! I began taking salads and left overs from the previous nights supper for lunch.

The biggest health habit we took from the first 10 days was to fix stone cut oatmeal and eggs with salsa every morning. We would fix a crockpot recipe of oatmeal over the weekend and just heat it up every morning. This is a habit we've continued after the challenge. I put salsa on a ton of stuff nowadays!

After the first week, I lost 14 lbs!

The following week came around, headaches were gone and I learned that I was beginning to form healthier habits! We continue to follow the Advocare challenge and the second week was drastically reduced but still lost 2.6 lbs!

Days 11-24

We largely stayed on the same routine as days 1-10 with the exception of we swapped out eggs and oatmeal for breakfast for the meal replacement breakfast shakes. I had the Chocolate flavored. I was impressed by the flavor. I've had protein shakes before and am not a big fan of the taste, too chalky. This was like a chocolate milkshake. I'd just mix it with water but if you mix it with ice and put it in the blender, it's even better because you don't have clumps in it! These meal replacement shakes were definitely more convenient! 

The biggest challenge during this time was taking the larger MNS pills. They are about the size of the One-A-Day pills. I've always had trouble taking pills. This period of the challenge, you do take a lot of pills! I had trouble swallowing the larger ones. I ended up mixing the pills with natural, no sugar added applesauce. This coated the pills and eventually made it much easier to swallow but it was an adjustment for me!

In regards to diet, we continued eating lean meat, salads and developing healthier habits. One of my favorite meals now is taco salad! Don't think big taco shell, this taco salad has ground turkey with taco seasoning with lettuce, green pepper, and onion and top it off the salsa and maybe even some sunflower kernels! Yummy!

After day 21 I lost another 6 lbs and after 24 days, I lost a total of 24 lbs! This was strictly diet changes. I didn't change anything in regards to physical activity.

For inquiring minds, my wife ended up losing a total of 21.4 lbs!

After Advocare 

I'm writing this a few weeks after finishing the challenge. While not at the Advocare rate, I am continuing to lose weight. For the most part we have continued our healthy eating habits. We continue to fix eggs and salsa in the morning and have healthy dinners. I've only gone out to lunch once at work and continue to take left overs for lunch. Some of my co-workers have even started packing!

For a week or so after the challenge I felt hungry A LOT and even still do to some degree! The Advocare appetite suppressants really work! My wife and I have continued to encourage each other. I could not have gone down this journey without her!

We hope and pray that we continue going down this healthier way of living both for our health as well as our growing babies health. I'm grateful for all my friends and family in being encouraging during this time and even sometimes adjusting meals to be more "Advocare friendly".

We have decided we are going do another 24 day challenge towards the end of the year. You're supposed to wait 3 months before doing it again. I'm excited to see what the results from those will be! My goal is to incorporate exercise this time around!

I would highly recommend anyone try Advocare both to lose weight but also to begin forming healthier habits. We went into this not thinking this is a diet but a new lifestyle. Advocare is a springboard to changing your life!

Monday, September 17, 2012

Importance of a Complete Vertical Slice

What's a vertical slice?  Think of a delicious layered cake.  Say we have 3 layers and you slice a piece.  A thin slice of each layer produces one solid piece.  Think of the cake layers as architectural pieces: database layer, services layer, the user interface layer, etc..  Each of these layers are as important as the last to get to the final goal: a solid, functional piece of software.

In any project, especially a green field project, building in vertical slices is critical to success.  A solid vertical slice proves two things: 
1.) Proven architecture
2.) Produces a complete, functional, shippable piece of working software that works from end to end.

The risk of not having a Vertical Slice

Not having a vertical slice presents an unproven architecture and much unneeded risk.  Not having a vertical slice poses the possibility that the entire database is built with no user interface or service layer, or the opposite, a great looking UI and service layer but the data model is a mess and not scalable.  Either way, much rework is involved for further scalability.  Having a proven architecture by developing in vertical slices allows you the ability to continue working and not end up with a fantastic UI but a non-scalable database model.

Don't forget ETL (Extract Transform Load)

When developing a vertical slice, consider the notion of having to importing existing data.  Does this change the implementation?  Can the data model be simplified or restructured to suite an ETL more effectively?  While I'm not saying to develop an application for the sole purpose of an ETL, the ETL needs to be considered in the vertical slice.

But individuals know one layer...

WRONG!  One characteristic of a good agile team are generalized specialists.  Individuals who may specialize in one layer or area but also able to build up the layers.  Ideally, team members' skills should complement each other's in order to create an effective synergy.  Have team members pair often to help facility the synergy and allow team members to grow from one another.  This type of cross functional team mentality allows vertical slices to be built effectively.  Thus coming to value added software quicker.

Identifying the vertical slice and developing a story via a vertical slice rather than by architectural layers proves the architecture and produces a piece of quality, shippable software faster.