Skip to content

Commit

Permalink
Add ability to pass in custom values via config
Browse files Browse the repository at this point in the history
Currently the config Quke exposes is for controlling how it runs and behaves. However feedback has shown that projects based on Quke often require their own configuration values. A common example is usernames and passwords for accounts when testing features that require authentication.

Now there are options for dealing with this; setting environment variables and then reading them in within the project being the most obvious solution. You could even write your own configuration mechanism if you had the necessary skills.

However Quke is specifically targeted at team members who may not have development backgrounds, and therefore aims to make creating acceptance tests as simple as possible.

For this reason, and from speaking with current users we have chosen to extend the existing configuration functionality in Quke to allow users to add their own custom values, which they can then access from the Quke config class within their projects. This means users only have to think about one source for all the configuration within their projects, the `.config.yml` file.

This change adds a new method to `Quke::Configuration` called `custom()`, which returns whatever values have been set under a root node called `custom` in the `.config.yml` file. Being YAML, this could be simple key value pairs, or a whole new object in itself.

We have also expanded the section on configuration in the README.md to cover this, providing examples of the things you can add and how to access them from your projects.
  • Loading branch information
Cruikshanks committed Mar 7, 2017
1 parent 9997ba8 commit ef49baf
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 5 deletions.
27 changes: 26 additions & 1 deletion .config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,31 @@ stop_on_error: 1
# elements that take some time to load you can increase this default.
max_wait_time: 5

# Anything you place under the 'custom' node in the `.config.yml` file will be
# available within your steps and page objects by calling
# `Quke::Quke.config.custom`. So using the example below we could access its
# values in the following ways
#
# Quke::Quke.config.custom["default_org_name"] # = "Testy Ltd"
# Quke::Quke.config.custom["accounts"]["account2"]["username"] # = "john.doe@example.gov.uk"
# Quke::Quke.config.custom["urls"]["front_office"] # = "http://myservice.service.gov.uk"
#
# As long as what you add is valid YAML (check with a tool like
# http://www.yamllint.com/) Quke will be able to pick it up and make it
# available in your tests.
custom:
default_org_name: "Testy Ltd"
accounts:
account1:
username: jane.doe@example.gov.uk
password: Av3rystr*ngone
account2:
username: john.doe@example.gov.uk
password: An*th3rstrongone
urls:
front_office: "http://myservice.service.gov.uk"
back_office: "http://admin-myservice.service.gov.uk"

# If you are running Quke behind a proxy you can configure the proxy details
# here. You'll need either the hostname or IP of the proxy server (don't include
# the http:// bit) and the port number (typically 8080). Currently proxy
Expand Down Expand Up @@ -64,7 +89,7 @@ browserstack:
project: 'Adding browserstack support'

# Allows you to specify an identifier for the test run.
# If you intend to repeat a test this might not be that aplicable, but in the
# If you intend to repeat a test this might not be that applicable, but in the
# case of one off tests it might be useful
name: 'Testing google search'

Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ Or install it yourself as

## Configuration

You can use configuration to drive Quke. You can configure Quke using `.config.yml` files. See [.config.example.yml](.config.example.yml) for details of the options to include in your `.config.yml`.
You can configure Quke using a `.config.yml` file. What can be configured essentially falls into one of 3 groups.

- **Quke configuration** - things like which driver to use, whether to pause between steps, or if Quke should stop in the event of an error
- **Custom configuration** - add your own custom values using the `custom:` node
- **Browserstack configuration** - specify exactly how you want your Browserstack session to run, for example which browser and OS to test against, the project name, and your credentials.

See [.config.example.yml](.config.example.yml) for full details of the options you can specify in your `.config.yml`.

### Multiple configs

Expand Down
9 changes: 8 additions & 1 deletion lib/quke/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ def use_proxy?
proxy['host'] == '' ? false : true
end

def custom
@data['custom']
end

# Override to_s to output the contents of Config as a readable string rather
# than the standard object output you get.
def to_s
Expand All @@ -152,18 +156,21 @@ def load_data

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def default_data!(data)
data.merge(
'features_folder' => (data['features'] || 'features').downcase.strip,
'app_host' => (data['app_host'] || '').downcase.strip,
'driver' => (data['driver'] || 'phantomjs').downcase.strip,
'pause' => (data['pause'] || '0').to_s.downcase.strip.to_i,
'stop_on_error' => (data['stop_on_error'] || 'false').to_s.downcase.strip,
'max_wait_time' => (data['max_wait_time'] || Capybara.default_max_wait_time).to_s.downcase.strip.to_i
'max_wait_time' => (data['max_wait_time'] || Capybara.default_max_wait_time).to_s.downcase.strip.to_i,
'custom' => (data['custom'] || nil)
)
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity

# rubocop:disable Metrics/MethodLength
def browserstack_data(data)
Expand Down
2 changes: 1 addition & 1 deletion lib/quke/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Quke #:nodoc:
VERSION = '0.2.8'.freeze
VERSION = '0.3.0'.freeze
end
15 changes: 15 additions & 0 deletions spec/data/.custom_complex_object.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
custom:
my_key: my_value
accounts:
account1:
username: yoda
password: greenisgood
account2:
username: vadar
password: redrules
account3:
username: luke
password: fatherissues
troop_numbers:
dark_side_count: 1000000
light_side_count: 5
2 changes: 2 additions & 0 deletions spec/data/.custom_key_value_pair.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
custom:
my_key: my_value
6 changes: 6 additions & 0 deletions spec/data/.custom_key_value_pairs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
custom:
my_key1: my_value1
my_key2: my_value2
my_key3: my_value3
my_key4: my_value4
my_key5: my_value5
56 changes: 55 additions & 1 deletion spec/quke/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@

describe '#proxy' do
context 'when NOT specified in the config file' do
it 'defaults to a blank values' do
it 'defaults to blank values' do
Quke::Configuration.file_location = data_path('.no_file.yml')
expect(subject.proxy).to eq('host' => '', 'port' => 0, 'no_proxy' => '')
end
Expand Down Expand Up @@ -186,6 +186,60 @@
end
end

describe '#custom', focus: true do
context 'when NOT specified in the config file' do
it 'defaults to nothing' do
Quke::Configuration.file_location = data_path('.no_file.yml')
expect(subject.custom).to be(nil)
end
end

context "when 'custom' in the config file holds simple key value pairs" do
it 'returns the key value pair if there is just one' do
Quke::Configuration.file_location = data_path('.custom_key_value_pair.yml')
expect(subject.custom).to eq('my_key' => 'my_value')
end

it 'returns all key value pairs if there are multiples' do
Quke::Configuration.file_location = data_path('.custom_key_value_pairs.yml')
expect(subject.custom).to eq(
'my_key1' => 'my_value1',
'my_key2' => 'my_value2',
'my_key3' => 'my_value3',
'my_key4' => 'my_value4',
'my_key5' => 'my_value5'
)
end
end

context "when 'custom' in the config file holds a hierachical object", focus: true do
it 'returns a representation of the object' do
Quke::Configuration.file_location = data_path('.custom_complex_object.yml')
expect(subject.custom).to eq(
'my_key' => 'my_value',
'accounts' => {
'account1' => {
'username' => 'yoda',
'password' => 'greenisgood'
},
'account2' => {
'username' => 'vadar',
'password' => 'redrules'
},
'account3' => {
'username' => 'luke',
'password' => 'fatherissues'
}
},
'troop_numbers' => {
'dark_side_count' => 1_000_000,
'light_side_count' => 5
}
)
end
end
end

describe '#to_s' do
it 'return the values held by the instance and not an instance ID' do
Quke::Configuration.file_location = data_path('.no_file.yml')
Expand Down

0 comments on commit ef49baf

Please sign in to comment.