Monday, March 19, 2012

Connect Rails 3.1 From Mac OS X to SQL Server


I’m currently using Ruby on Rails 3.1 and am developing on a Mac.  A requirement was to use MS SQL Server as the database.  There are a couple hoops to jump through to get RoR to work with SQL Server.  Fortunately, the Tiny TDS gem made this a breeze to setup without having to go through the headache of unixodbc/iodbc/rubyodbc configuration.

Here’s the following steps to accomplish:

1.  Install FreeTDS using brew

brew install freetds

2.  Add the following gems to the Gemfile

  gem 'activerecord-sqlserver-adapter'
  gem 'tiny_tds'

3.  Run bundle install to update the gems

4.  Modify the database.yml file to the following:

development:
    adapter: sqlserver
    mode: dblib
    dataserver:   <IP Address>\<Instance Name>
    database: database_name
    username: sql_user
    password: sql_password

Things of note:


1.  Additional ways to configure the connection string can be found here

2.  If you’re using a named instance of SQL, it’s not going to use the default 1433 port.  Through SQL Management Studio, you can run the following command to find out what port your instance is running on:

use master
go
xp_readerrorlog

Troubleshooting


If this doesn’t initially work, there are a couple potential points of failure.  Here are some of the debugging techniques I used to verify I could connect to SQL Server without rails:

1.  Verify that you can make a connection to SQL Server.  From terminal prompt, do the following:

telnet <IP Address> <port>

If you connect, you'll receive the following:

Trying 192.168.31.128...
Connected to 192.168.31.128.
Escape character is '^]'.


2.  Once you’ve verified that you can connect using telnet, second step is to verify that you can connect via FreeTDS.  From the terminal prompt, do the following:

tSQL –H <IP Address> –p <Port> –U sa -P password

If connected properly, you should see the following prompt:
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1>

At this point, this is a SQL editor so you could use SQL syntax to extract queries.  For our purposes, we just want to verify that we can connect this way. 

Type exit to exit out of application

3.  I also ran into an issue when connecting using Rails I received the following error “Adaptive Server timeout”.  I resolved this by doing another bundle install and it has worked after that.

Happy Developing!

Saturday, March 3, 2012

SpecFlow 101

SpecFlow is a Behavior Driven Development (BDD) tool for .NET.  SpecFlow has brought the Gherkin language to .NET and to Visual Studio!  This post will set you up quickly with SpecFlow with a simple example.  

Install

Download the latest SpecFlow install

New Visual Studio Templates

image

Once installed, there are three new Visual Studio templates that will be installed including the

  • Event Definition – this template is to be used for more of global hooks such as
  • Feature – template to write out the feature with scenarios in Gherkin language
  • Steps Definition – template to store the steps from the feature file that will execute the code and do assertions

Our Feature Example

For this example, we’ll use the Roman Numeral kata.  While this is a relatively simple kata, the purpose is to help navigate through SpecFlow.  So, let's begin:

1.  Create a new project and create a SpecFlow Feature File:

image

2.  Create a SpecFlow Step Definition File

The Step Definition template has code with sample steps in the class.  Delete everything inside the class but not the class itself.

3.  Generating Steps from Feature file

There are a couple of different ways to generate steps once a scenario is given.

  • Step by Step – with your cursor over a scenario step, press F12.  image

SpecFlow will offer to put the step binding skeleton in your clipboard and then it can be easily pasted into your steps definition file.  Note that if the step already exists, Specflow will navigate you to the step definition automatically, just like F12 does with “GoTo Definition”.

This is useful when you’re creating a new feature and want to take one step at a time versus having numerous pending steps.  I find this useful when you want to take things one at a time.

  • Bulk Create

Using TestDriven.Net right click on the feature designer file (extension of .feature.cs) click “Run Test(s)”.  For each scenario, SpecFlow will create a task that contains a StepsDefinition class.  This class can be copied and pasted into the steps definition file.   It should look like the following:

image

Observations:

  • With each generated step, the result will be Pending
  • One class per scenario.  When generating steps, SpecFlow will generate one steps definition class that is in the feature file if none exists.  There could exist the same step in multiple scenarios, neither of which have been generated yet.  When pasting in the generated steps, you’ll get compile errors telling you of duplicate steps.  Delete the duplicate steps and you’re golden.
  • If two of the same steps exists and you manually change the method name but leave the regex decorator the same, there will be a runtime error noting ambiguous steps.
  • If attempting to navigate to a step from a feature file with multiple regex step definitions matching, SpecFlow will throw a dialog box up stating ambiguous steps and will navigate to the first one.

Developing Code to Make The Test Pass

By default, SpecFlow is setup to use NUnit.  You can configure SpecFlow to use MSTest, if so desired.  Generate the steps with the correct xUnit assertion statements to make the tests pass for each step. 

Running Tests

Running Tests are very similar to generating the steps.  Once the steps are generated and beautiful code is written to get the tests to pass, right click on the feature designer file and click “Run Test(s)”.  If steps within a scenario are still pending, the following message will be displayed:

image

Hopefully this gets you familiar with SpecFlow and some of the advantages of this tool being integrated into Visual Studio.  Happy trails with your SpecFlow journey!