Permalink
Browse files

Set up rake tasks to make running features easier

Three things here:

1. I'm going to translate features over, and mark them as failing when
they are failing. I'll also tag them with gh-N to mark GitHub issue #N
that they go along with.
2. `bin/rake cruise` has been set up to run for CI. Basically, it runs all
the things that aren't failing, and makes sure they pass. Then, it runs
all thet hings that are supposed to be failing, and makes sure they
fail. If either of those are not true, it fails the build, and if
they both pass, they pass. This way we know when something starts
passing again, and to remove the failing tag.
3. `bin/rake focus` is added when developing new scenarios. You just tag
the scenario you're working on with `@focus`, and then `bin/rake focus`
will run just that one scenario.
  • Loading branch information...
steveklabnik committed Dec 10, 2013
1 parent 0249dca commit 999670a5b67ecdf80105e912d89171b4648cd7b6
View
@@ -1,4 +1,4 @@
language: ruby
rvm:
- 2.0.0
-script: ./bin/cucumber --format=progress
+script: bin/rake cruise
View
@@ -3,3 +3,4 @@ source "https://rubygems.org"
gem "cucumber"
gem "httparty"
gem "json-schema"
+gem "rake"
View
@@ -19,6 +19,7 @@ GEM
multi_json (1.8.2)
multi_test (0.0.2)
multi_xml (0.5.5)
+ rake (10.1.0)
PLATFORMS
ruby
@@ -27,3 +28,4 @@ DEPENDENCIES
cucumber
httparty
json-schema
+ rake
View
@@ -44,3 +44,34 @@ Running Tests
$ bundle
$ bin/cucumber
```
+
+This requires Ruby. We run the changes with Ruby 2.0, but other versions will
+probably work as well. [Let us
+know](https://github.com/balanced/balanced-api/issues/new) if you have any
+problems running these specs, and we'd be happy to help.
+
+If you're working on a new scenario, the 'focus' task is useful. Tag a scenario
+with `@focus`, and then run `bin/rake focus`. It will only run that single scenario.
+
+### Discussions around changes
+
+Speaking of issues, that's the second purpose of this repository. If you would
+like to see a new feature implemented in the Balanced API, please [open an
+issue](https://github.com/balanced/balanced-api/issues/new) and we'll discuss
+it.
+
+For example, one of our biggest requests is to support non-USD currencies.
+[Here](https://github.com/balanced/balanced-api/issues/23) is the issue with
+the discussion, and when we support this feature, we close the issue via a pull
+request that implements the specification, and then everyone on the issue gets
+notified.
+
+Sometimes, Issues are great for collecting feedback, as well. For example,
+[all implementation of the current framework was done via
+PR](https://github.com/balanced/balanced-api/pull/431), and some issues need
+more explanation around use cases by those who want the feature, like [Bitcoin
+support](https://github.com/balanced/balanced-api/issues/204).
+
+We try to do as much 'internal' discussion in these issues as well, it's not
+just for public feedback. If you want to know what we're thinking, just search
+for a relevant issue!
View
@@ -0,0 +1,52 @@
+require 'cucumber/rake/task'
+
+class BuildFailure < Exception;
+ def initialize(message = nil)
+ message ||= "Build failed"
+ super(message)
+ end
+end;
+
+Cucumber::Rake::Task.new do |t|
+ t.cucumber_opts = "--format progress --tags ~@failing"
+end
+
+Cucumber::Rake::Task.new(:focus) do |t|
+ t.cucumber_opts = "--format progress --tags @focus"
+end
+
+namespace :features do
+ desc "Run all features"
+ Cucumber::Rake::Task.new(:all) do |t|
+ t.cucumber_opts = "--format progress"
+ end
+
+ desc "Run in-progress features"
+ Cucumber::Rake::Task.new(:in_progress) do |t|
+ t.cucumber_opts = "--require formatters/ --format Cucumber::Formatter::InProgress --tags @failing"
+ end
+end
+
+desc "Run complete feature build"
+task :cruise do
+ finished_successful = run_and_check_for_exception("cucumber")
+ in_progress_successful = run_and_check_for_exception("features:in_progress")
+
+ unless finished_successful && in_progress_successful
+ puts
+ puts("Finished features had failing steps") unless finished_successful
+ puts("In-progress Scenario/s passed when they should fail or be pending") unless in_progress_successful
+ puts
+ raise BuildFailure
+ end
+end
+
+def run_and_check_for_exception(task_name)
+ puts "*** Running #{task_name} features ***"
+ begin
+ Rake::Task["#{task_name}"].invoke
+ rescue Exception => e
+ return false
+ end
+ true
+end
View
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+#
+# This file was generated by Bundler.
+#
+# The application 'rake' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'pathname'
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
+ Pathname.new(__FILE__).realpath)
+
+require 'rubygems'
+require 'bundler/setup'
+
+load Gem.bin_path('rake', 'rake')
View
@@ -2,13 +2,13 @@ Feature: Tokenize a credit card
"Tokenizing" a credit card is the process of sending Balanced a credit card
number for storage. The API will then give the customer back a token that the
customer will store. The idea is that if a customer stored the credit card data
- directly, the customer would legally be required to take extra precautions for
- safely storing the information, whereas with the token, Balanced worries about
+ directly, the customer would legally be required to take extra precautions for safely storing the information, whereas with the token, Balanced worries about
that, and the customer just charges against the token rather than the card.
For more on tokenization as a concept, see ['tokenization' on
Wikipedia.](http://en.wikipedia.org/wiki/Tokenization_%28data_security%29)
+ @failing
Scenario: Tokenize a card without a secret key
Cards are able to be tokenized without sending along a secret key. When
this happens, the customer gets less information than if the key was sent.
@@ -35,3 +35,6 @@ Feature: Tokenize a credit card
}
"""
+ When I GET "cards.href" from the previous response
+ Then I should get a 200 OK status code
+ And the response is valid according to the "cards" schema
@@ -1,4 +1,3 @@
-require 'httparty'
require 'json-schema'
When(/^I POST to (\/.*) without my secret key with the JSON API body:$/) do |url, body|
@@ -20,3 +19,26 @@
Then(/^the response has this schema:$/) do |schema|
assert JSON::Validator.validate(JSON.parse(schema), @response_body)
end
+
+When(/^I GET "(.*?)" from the previous response$/) do |keys|
+ # hax to access a Ruby hash like dot notation
+ # Array shennanigans is because we only support the first element
+ url = keys.split('.').inject(@response_body) {|o, k| Array(o[k])[0] }
+ options = {
+ headers: {
+ "Accept" => "application/vnd.api+json;revision=1.1",
+ },
+ basic_auth: {
+ username: $api_secret,
+ password: "",
+ }
+ }
+
+ response = HTTParty.get("https://api.balancedpayments.com#{url}", options)
+ @response_code = response.code
+ @response_body = JSON.parse(response.body)
+end
+
+Then(/^the response is valid according to the "(.*?)" schema$/) do |filename|
+ assert JSON::Validator.validate(File.join("fixtures", "#{filename}.json"), @response_body), "The response failed the '#{filename}' schema. Here's the body: #{@response_body}"
+end
@@ -0,0 +1,27 @@
+require 'httparty'
+require 'json'
+
+# First, we need to create an API key. This is as easy as making a POST request.
+
+options = {
+ headers: {
+ "Accept" => "application/vnd.api+json;revision=1.1",
+ },
+}
+response = HTTParty.post("https://api.balancedpayments.com/api_keys", options)
+$api_secret = JSON.parse(response.body)["api_keys"][0]["secret"]
+
+# Now that we have our key, we need to make a marketplace. Lots of our scenarios
+# will fail unless we've made at least one.
+
+options = {
+ headers: {
+ "Accept" => "application/vnd.api+json;revision=1.1",
+ },
+ basic_auth: {
+ username: $api_secret,
+ password: ""
+ },
+}
+
+HTTParty.post("https://api.balancedpayments.com/marketplaces", options)
View
@@ -1,10 +0,0 @@
-require 'httparty'
-require 'json'
-
-options = {
- headers: {
- "Accept" => "application/vnd.api+json;revision=1.1",
- },
-}
-response = HTTParty.post("https://api.balancedpayments.com/api_keys", options)
-$api_secret = JSON.parse(response.body)["api_keys"][0]["secret"]
@@ -0,0 +1,54 @@
+{
+ "$schema": "http://json-schema.org/draft-03/schema#",
+ "type": "object",
+ "properties": {
+ "line1": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "required": true
+ },
+ "line2": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "required": true
+ },
+ "city": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "required": true
+ },
+ "state": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "required": true
+ },
+ "postal_code": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "required": true
+ },
+ "country_code": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "type": "string",
+ "pattern": "[A-Z]{2}"
+ }
+ ],
+ "required": true
+ }
+ },
+ "additionalProperties": false
+}
Oops, something went wrong.

0 comments on commit 999670a

Please sign in to comment.