Tag Archives: rspec

Introduction
In my previous article I have explained how to create our own ruby gem using bundler. Writing own gem is a good idea but if you add test cases for your gem it will be useful for other developers to understand what your gem will do. In this article I am going to explain how to write test cases for our gem using Rspec & creating configuration file using generators.

Test Our Own Gem
Install all the dependencies listed in previous article. Open the wavelabs_client_api.gemspec file & add the following line:

    spec.add_development_dependency "rspec"
  

‘rspec’ is a testing framework gem. After adding above line save the file and run ‘bundle install’ from our gem root directory. It will install the ‘rspec’ gem. Once you install the gem initialize the spec/ directory (where specs will reside) with:

    $rails generate rspec:install
  

This adds the following files which are used for configuration:

  • .rspec
  • spec/spec_helper.rb
  • spec/rails_helper.rb

Now we are ready to write test cases for our gem. In spec_helper.rb file ‘require’ all the dependencies to test our gem.

    require 'wavelabs_client_api' 
    require 'byebug'

    require 'support/user_sign_up.rb'
    # and any other gems you need
   

And also you need to add if you have any ENV variables needed for your gem for testing. After configuration you need to create your spec files under /spec directory. You can create your own namespace depending on your choice. In each of your spec file needs to ‘require’ spec_helper.rb file. ANd follow the naming rspec convention for spec files. Following is my spec directory structure:

owngem_test1

Example Spec file:

   #File /spec/auth_api_spec.rb
    require 'spec_helper'

describe WavelabsClientApi::Client::Api::Core::AuthApi do

  let (:auth_api_obj) { WavelabsClientApi::Client::Api::Core::AuthApi.new}
  let (:auth_api) { WavelabsClientApi::Client::Api::Core::AuthApi}

  it "#check_connection?" do
    expect(auth_api.check_connection?).to be true
  end 

  it "#Check Constants of Auth API URIS" do
    expect(auth_api::AUTH_TOKEN_URI).to eq '/oauth/token'
    expect(auth_api::TOKEN_VALIDATION_URI).to eq '/api/oauth/v0/tokens'
    expect(auth_api::LOGIN_URI).to eq '/api/identity/v0/auth/login'
    expect(auth_api::LOGOUT_URI).to eq '/api/identity/v0/auth/logout'
    expect(auth_api::CHANGE_PASSWORD_URI).to eq '/api/identity/v0/auth/changePassword'
    expect(auth_api::FORGOT_PASSWORD_URI).to eq '/api/identity/v0/auth/forgotPassword'
  end

  it "#get_auth_token with client details" do
    res = auth_api_obj.get_auth_token("client_credentials", "oauth.client.r")
    expect(res[:status]).to eq 200
  end
  ....... 
  

You can find the original specs for wavelabs_api_client here. After adding all test cases use the ‘rspec’ command to run your specs:

    bundle exec rspec
   

By default the above will run all _spec.rb files in the spec directory. For more details about this see the RSpec spec file docs.

To run only a subset of these specs use the following command:

# Run only model specs
bundle exec rspec spec/models

# Run only specs for AccountsController
bundle exec rspec spec/controllers/accounts_controller_spec.rb

Specs can also be run via rake spec, though this command may be slower to start than the rspec command.

Creating generator
It’s time to add a generator for our own gem. wavelabs_client_api gem needs API server details to communicate. Using generator we can create migrations, views, controllers & configuration files ..etc.

If you’ve written a gem at some point you might want to have configuration options for those people using the gem. Luckily, this is relatively easy to do with a configure block.

The code inside your lib/[gemname].rb should look something like this:

    module WavelabsClientApi

  class << self
    attr_accessor :configuration
  end

  def self.configure
    self.configuration ||= Configuration.new
    yield(configuration)
  end

  class Configuration
    attr_accessor :api_host_url, :client_key, :client_secret
  end

end
  

The gist is here all we do is add a configure method that allows us to store whatever options we want inside of the of the Configuration class. In this case, we only have three variables to configure: api_host_url, client_key, client_secret. However, if we were to add more, we simple just add an attr_accessor for each of the configuration options.

Now from anywhere in our gem we can look at WavelabsClientApi.configuration.api_host_url if we want to see what that value is set to.

Additionally, this allows us to do something like the following in our config/initializers/wavelabs_client_api.rb to configure our gem before we use it:

   WavelabsClientApi.configure do |config|
     config.api_host_url = 'API_HOST_URL'
     config.client_key = 'API_CLIENT_KEY'
     config.client_secret = 'API_CLIENT_SECRET'
   end
  

Well, that’s nice, but what if we want to generate the config/initializers/wavelabs_client_api.rb for those that use our gem. Luckily, Rails provides us with generators.

Inside our lib folder we should create a generators folder and inside of that two new folders: [gem_name] and templates.

Inside the templates folder we should put our default initializer file, such that lib/generators/templates/wavelabs_client_api_initializer.rb looks something like the following:

   WavelabsClientApi.configure do |config|
     config.api_host_url = 'API_HOST_URL'
     config.client_key = 'API_CLIENT_KEY'
     config.client_secret = 'API_CLIENT_SECRET'
   end
  

Note that it’s extremely helpful to those using your gem to have comments about what certain options do right inside the generated initializer file.

Now we can write or generator to copy over the file when someone runs:

   rails g [gemname]:install
 

We create a lib/generators/wavelabs_client_api/install_generator.rb file to do so and it should look something like:

   module WavelabsClientApi
  module Generators
    class InstallGenerator < Rails::Generators::Base
      source_root File.expand_path("../../templates", __FILE__)
      desc "Creates wavelabs client api initializer for your application"

      def copy_initializer
        template "wavelabs_client_api_initializer.rb", "config/initializers/wavelabs_client_api.rb"

        puts "Install complete! Please make sure to set following ENV variables!"
        puts "ENV['API_HOST_URL'] = 'site url' "
        puts "ENV['CLIENT_ID'] = 'XXXXXX'"
        puts "ENV['CLIENT_SECRET'] = 'XXXXXXXXX' "
      end
    end
  end
end
 

Every single public method inside of this class will be executed as part of the generator process. The magic line that you really care about is this one here:

   template "wavelabs_client_api_initializer.rb", "config/initializers/wavelabs_client_api.rb"
  

This is what copies the contents of our initializer template over to the application’s initializers.

Conclusion

In this article I have covered how to write test cases for our own ruby gem using rpsec & how to create generator for the gem. Thanks for reading this article!