Sitemap

Set up a Postgresql database for your test environment in Sinatra (step-by-step)

Rob Faldo
4 min readJun 8, 2018

When we run our tests, we want to be able to expect what the outcome will be, which will be impossible if we’re using live (and changing) data that is in our production environment. To control the data that our tests will use, we need to set up a separate database and build a test environment for our web application, where we include a script that resets our database after every time we run our tests.

What we’re doing: Setting up a new database is Postgresql

Why we’re doing it: So that we can use a separate database for our tests, where we can control what data goes into it without affecting our production database.

Roberts-MacBook-Pro:bookmark_manager robertfaldo$ psql
psql (10.4)
Type "help" for help.
robertfaldo=# CREATE DATABASE rpschallenge_test;
CREATE DATABASE
robertfaldo=# \c rpschallenge_test;
You are now connected to database "rpschallenge_test" as user "robertfaldo".
rpschallenge_test=# CREATE TABLE scoreboard (id VARCHAR(60) PRIMARY KEY, gameswon INT, gameslost INT);
CREATE TABLE
rpschallenge_test=# SELECT * FROM scoreboard;
id | gameswon | gameslost
----+----------+-----------
(0 rows)

What we’re doing: Creating an ENV variable whenever our tests run.

Why we’re doing it: So that our program will know when we’re running tests to trigger it to use the test database and not the production database.

How we’re doing it: We can include the below line in your spec_helper.rb. Because RSpec always runs your spec_helper.rb file, every time our tests run, the below code will set the ENV key ENVIRONMENT to a value of ‘test’. We can then check whether the ENV has a key => value pair of ‘ENVIRONMENT’ and ‘test’ to decide whether to use the production database or our test database (following step below this one does this).

# in spec_helper.rbENV['ENVIRONMENT'] = 'test'

What we’re doing: Use the ENV variable to pick the test database whenever running tests

Why we’re doing it: We use the test database so that we can control its content and not impact our production database.

How we do it: We edit the Class that is connecting to the database in our model to include an if statement that when the ENV[‘ENVIRONMENT’] is set to test (i.e. when we run our RSpec, which will first run our spec_helper.rb file which has the above code in it to trigger this if statement) then it will connect to the test database. When our code is executed without the ENV[‘ENVIRONMENT’] then it will connect to the normal database.

# BEFORE we add the if statement. All environments (production, development and testsing#in scoreboard.rbrequire 'pg'class Scoreboard  def self.show  # create a connection with the database
connection = PG.connect(dbname: 'rpschallenge')
# execute the sql query & store in variable
result = connection.exec('SELECT * FROM scoreboard')
# map the variable, creating a new variable that holds games won and games lost
result.map do|player|
{
id: player['id'],
gameswon: player['gameswon'],
gameslost: player['gameslost']
}
end
end
#AFTER we add the if statement.class Scoreboard def self.show if ENV['ENVIRONMENT'] == 'test'
# create a connection to the test database
connecton = PG.connect(dbname: 'rpschallenge_test')
else
# create a connection to the production database
connection = PG.connect(dbname: 'rpschallenge')
end
# execute the sql query & store in variable
result = connection.exec('SELECT * FROM scoreboard')
# map the variable, creating a new variable that holds games won and games lost
result.map do |player|
{
id: player['id'],
gameswon: player['gameswon'],
gameslost: player['gameslost']
}
end
end

Make sure tests run against an empty database

What we’re doing: Create a method that clears the table in our test database

Why we’re doing it: So that we can call the method before every test, so that every test is working from a clean database.

How we do it: We’ll need to create a setup_test_database.rb document and make a method that empties the database

#in setup_test_database.rbrequire 'pg'
def setup_test_database!
​ p "Setting up test database..."​ # Connect to the test database
connection = PG.connect(dbname: 'rpschallenge_test')
# Clear the database
connection.exec("TRUNCATE scoreboard;")
​end

Why is there a ! at the end of the method? Read more here.

What we’re doing: Run the method that clears our table in our tests database before every test we run

Why we’re doing it: We want every test to start with an empty database, so that we can accurately predict that the ‘exercise’ step of our test is what is being verified in our ‘verify’ step in our test. (see 4 phases of testing)

How we’re doing it: We’re including the below in our spec_helper folder, which runs our setup_test_database! method before each test.

#in spec_helper.rb# requires the document that the setup_test_database! method is
require 'setup_test_database'
​# Before each test, run the method setup_test_database!
RSpec.configure do |config|
config.before(:each) do
setup_test_database!
end
end

What we’re doing: Now, for each test we run, our test database will be empty (because we truncated it). Therefore, in order to run your feature spec tests, you’ll need to add data to your tests database.

feature 'Viewing scoreboard' do  scenario 'A user can see the scoreboard on results page' do    # Creating connection to test databse
connection = PG.connect(dbname: 'rpschallenge_test')
# Adding data to the tests database
connection.exec("INSERT INTO scoreboard VALUES('Dave', 3, 1);")
connection.exec("INSERT INTO scoreboard VALUES('Lucy', 2, 6);")​ log_in_and_play
click_button('Paper')
expect(page).to have_content 'Dave 3 1'
expect(page).to have_content 'Lucy 2 6'
end
def log_in_and_play
visit("/")
fill_in('name', with: 'Rob')
click_button('Begin Game')
end
end

You also need to add data to the test database in your unit test

describe Scoreboard do  describe '.show' do
it 'returns all players and scores in an array' do
# Connect to your test database
connection = PG.connect(dbname: 'rpschallenge_test')

# Add data to your test database
connection.exec("INSERT INTO scoreboard VALUES('Dave', 3, 1);"
connection.exec("INSERT INTO scoreboard VALUES('Lucy', 2, 6);")
expected_array = [
{id: 'Dave', gameswon: "3", gameslost: "1"},
{id: 'Lucy', gameswon: "2", gameslost: "6"}
]
​ expect(Scoreboard.show).to eq expected_array
end
end
end​

--

--

Rob Faldo
Rob Faldo

Written by Rob Faldo

Ruby Engineer @ Simply Business

No responses yet