spanbars 0.1.2beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +69 -0
- data/bin/spanbars +97 -0
- data/features/01_spanbarprocessor_initialization.feature +29 -0
- data/features/02_spanbarprocessor_add.feature +40 -0
- data/features/03_spanbar_initialization.feature +30 -0
- data/features/04_spanbars_commandline.feature +19 -0
- data/features/step_definitions/01_spanbar_processor_initialization_steps.rb +36 -0
- data/features/step_definitions/02_spanbarprocessor_add_steps.rb +42 -0
- data/features/step_definitions/03_spanbar_initialization_steps.rb +18 -0
- data/features/step_definitions/04_spanbars_commandline_steps.rb +26 -0
- data/features/support/env.rb +6 -0
- data/features/support/ref1.csv +51464 -0
- data/features/support/ref1_out_0.25_25.csv +296 -0
- data/features/support/ref2.csv +6358 -0
- data/features/support/ref2_out_1_25.csv +28 -0
- data/features/support/ref3.csv +3566 -0
- data/features/support/ref3_out_0.0000005_10.csv +47 -0
- data/lib/spanbar.rb +147 -0
- data/lib/spanbarprocessor.rb +196 -0
- metadata +162 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7698dcae6b52fb67ba0636e83ed8c818bc517ed0ccce2559c4ae61e9c37bad62
|
4
|
+
data.tar.gz: c7472948c2e2f5809e910548677f016b510eeadd711414bae016c027e04b46a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cda1887acff3b220c43e0667202ccf6eaa83c1c9ccfa80b6610056e1eea1a786a83baa409f34b146b165a60a769c1b11caed87037a879725a7b42a9964ff6c0f
|
7
|
+
data.tar.gz: c9a98b5a5bf355ee6cec2c9602309d05da34f9293189c0fdfd9a4d1537de96eda539b116d5ec6438a62a3c72c8df4f987fedcc953e1c760272bd9559996d9a13
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# SpanBars
|
2
|
+
|
3
|
+
SpanBars is a tiny tool to produce span bars from time series data, either directly from a time
|
4
|
+
series or based on OHLC bars.
|
5
|
+
|
6
|
+
## Description
|
7
|
+
|
8
|
+
SpanBars reads record-by-record (or line-by-line) and provides the according span bars.
|
9
|
+
The current bar is closed and a new bar is created as soon as the given span is _exceeded_.
|
10
|
+
|
11
|
+
Spanbars are comparable to classic OHLC bars or candle sticks, but have the major
|
12
|
+
advantage of a CLOSE value always equalling either HIGH or LOW. All data eliminated
|
13
|
+
can be considered as _noise_.
|
14
|
+
|
15
|
+
Therefore exists 4 types of bars:
|
16
|
+
|
17
|
+
* TOP: CLOSE == HIGH
|
18
|
+
* UP: CLOSE == HIGH and OPEN == LOW
|
19
|
+
* BOTTOM: CLOSE == LOW
|
20
|
+
* DOWN: CLOSE == LOW and OPEN == HIGH
|
21
|
+
|
22
|
+
When generating spanbars based on a plain time series, these bars can be sent to output using
|
23
|
+
the parameter _--simple_. Without it will
|
24
|
+
process the resulting data again, aggregating all bars created in the first run to start
|
25
|
+
at an absolute HIGH (or LOW) and end at an absolute LOW (or HIGH resp.). Although these
|
26
|
+
spans of second type might be much larger than _--span_, they can be considered to
|
27
|
+
contain no noise _smaller or equal than_ span.
|
28
|
+
|
29
|
+
Creating spanbars from given OHLCs is slightly inaccurate, as even one OHLC might
|
30
|
+
contain several spanbars, but that cannot be reflected by the given input data. Also, for
|
31
|
+
processing OHLC-input data, note that the entire algorithm (simple spanbars first, strict spanbars seconds) is run 3 times:
|
32
|
+
1. using (span / 2) on input HIGHS
|
33
|
+
2. using (span / 2) on input LOWS
|
34
|
+
1. using (span) on [ resulting Highs, resulting Lows ].sorted\_by\_time
|
35
|
+
|
36
|
+
The application area this gem is written for is denoising data for trend recognition
|
37
|
+
within monitored timeseries.
|
38
|
+
|
39
|
+
## Basic usage
|
40
|
+
processor = SpanBarProcessor.new(span: 5)
|
41
|
+
File.read("./timeseries.csv").map{|x| { t: x[0], v: x[1] } }.sort_by{|x| x[:t]}.each do |data|
|
42
|
+
processor.add(data)
|
43
|
+
end
|
44
|
+
processor.bars.each {|x| puts x}
|
45
|
+
|
46
|
+
## Basic usage via commandline
|
47
|
+
|
48
|
+
Using _spanbars_ on the commandline expects data on STDIN as CSV with timestamps on column 1 and
|
49
|
+
values on column 2. With _--ohlc_ enabled, it expects CSV with "timestamps,open,high,low,close".
|
50
|
+
|
51
|
+
Provided output will be CSV as well, for
|
52
|
+
|
53
|
+
* _simple_: "timestamp\_open,open, timestamp\_high,high, timestamp\_low, low, timestamp\_close, close, direction, path, momentum, direction"
|
54
|
+
* _strict_: "timestamp\_open,open, timestamp\_close, close, duration, path, momentum, effective\_span, direction"
|
55
|
+
|
56
|
+
I currently plan to implement 2 more parameters: _--human_ to create a human-readable table
|
57
|
+
(particularly concerning the time format), and _--intraday_ (ommiting the date part when using _--human_).
|
58
|
+
|
59
|
+
$ cat timeseries.csv | spanbars
|
60
|
+
$ spanbars --input ./timeseries.csv --span 5
|
61
|
+
|
62
|
+
## List of parameters
|
63
|
+
|
64
|
+
* --span (defaults to 10)
|
65
|
+
* --ticksize (default to 1.0)
|
66
|
+
* --ohlc (defaults to false)
|
67
|
+
* --simple (defaults to false)
|
68
|
+
* --human (planned, defaults to false)
|
69
|
+
* --intraday (planned, defaults to false)
|
data/bin/spanbars
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
4
|
+
require File.dirname(THIS_FILE) + '/../lib/spanbarprocessor.rb'
|
5
|
+
require File.dirname(THIS_FILE) + '/../lib/spanbar.rb'
|
6
|
+
|
7
|
+
|
8
|
+
# prepare processing of incoming control commands (e.g. Ctrl-C)
|
9
|
+
Signal.trap("TERM") { local_interrupt }
|
10
|
+
Signal.trap("INT") { local_interrupt }
|
11
|
+
|
12
|
+
def local_interrupt
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
|
16
|
+
# prepare command line parser and help text
|
17
|
+
|
18
|
+
op = Slop::Options.new
|
19
|
+
op.banner = "\n#{"Usage:".light_white} spanbars [options]"
|
20
|
+
op.separator ""
|
21
|
+
op.bool '--simple' , "Disable processing of strict StanBars", default: false
|
22
|
+
op.float '--ticksize' , "Set ticksize for processing", default: 1.0
|
23
|
+
op.integer '--span' , "Set span for processing", default: 10
|
24
|
+
op.boolean '--ohlc' , "Define OHLC input file instead of timeseries (overrides --simple and --both)", default: false
|
25
|
+
op.boolean '--human' , "Define human output", default: false
|
26
|
+
op.boolean '--intraday' , "Strip date portion (affects --human only)", default: false
|
27
|
+
op.boolean '--help' , "Print this help", default: false
|
28
|
+
op.boolean '--both' , "Returns both simple and strict bars (overrides simple)", default: false
|
29
|
+
op.separator ""
|
30
|
+
op.separator "#{"Please note:".light_white} spanbars relies on STDIN data, e.g. "
|
31
|
+
op.separator " #{"$".light_white} cat /tmp/timeseries.csv | spanbars --simple --span 5 --ticksize 0.1"
|
32
|
+
op.separator ""
|
33
|
+
|
34
|
+
optparser = Slop::Parser.new(op)
|
35
|
+
|
36
|
+
# print help upon unparsable commandline options
|
37
|
+
begin
|
38
|
+
opts = optparser.parse(ARGV)
|
39
|
+
rescue StandardError => e
|
40
|
+
puts e.inspect
|
41
|
+
puts op.to_s
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
if opts.help?
|
46
|
+
puts op.to_s
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
unless STDIN.tty?
|
51
|
+
unless opts.ohlc?
|
52
|
+
s = SpanBarProcessor.new(opts)
|
53
|
+
while csv = STDIN.gets
|
54
|
+
line = CSV.parse(csv.chomp).flatten
|
55
|
+
result = s.add(line[0].to_i, line[1].to_f)
|
56
|
+
if result
|
57
|
+
if opts[:human]
|
58
|
+
result.each {|r| r.set_intraday if opts[:intraday]; puts ([:up, :bottom].include? r.type) ? "#{r.to_human}".green : "#{r.to_human}".red }
|
59
|
+
else # CSV output
|
60
|
+
result.each {|r| CSV {|out| out << r.to_a } }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
exit
|
65
|
+
else # if ohlc is given
|
66
|
+
data = [ ]
|
67
|
+
data << CSV.parse(csv.chomp).flatten while csv = STDIN.gets
|
68
|
+
opts = opts.to_hash
|
69
|
+
opts.delete(:simple)
|
70
|
+
opts.delete(:both)
|
71
|
+
highOpts = opts.dup
|
72
|
+
highOpts[:span] = (opts[:span] / 2.0).floor.to_i
|
73
|
+
highProc = SpanBarProcessor.new(highOpts)
|
74
|
+
lowProc = SpanBarProcessor.new(highOpts)
|
75
|
+
finProc = SpanBarProcessor.new(opts)
|
76
|
+
data.each do |d|
|
77
|
+
highProc.add(d[0].to_i, d[2].to_f)
|
78
|
+
lowProc. add(d[0].to_i, d[3].to_f)
|
79
|
+
end
|
80
|
+
res = highProc.spanBars.map{|bar| bar.type == :up ? bar.highval : bar.lowval } #.map{|peak| bar.highval }
|
81
|
+
res.flatten!
|
82
|
+
res.sort!{|a,b| a[:t] <=> b[:t]}
|
83
|
+
res.each {|peak| finProc.add peak[:t],peak[:p]}
|
84
|
+
if opts[:human]
|
85
|
+
finProc.spanBars.each {|r| r.set_intraday if opts[:intraday]; puts ([:up, :bottom].include? r.type) ? "#{r.to_human}".green : "#{r.to_human}".red }
|
86
|
+
else # CSV output
|
87
|
+
finProc.spanBars.each {|r| CSV {|out| out << r.to_a } }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
else
|
91
|
+
puts op.to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: Initializiation of SpanBarProcessor
|
2
|
+
Scenario: Testing provided arguments during initialization
|
3
|
+
* a new SpanBarProcessor created with span that is not Integer or <= 1 should raise ArgumentError
|
4
|
+
* a new SpanBarProcessor created with a valid span but non-Numeric ticksize or <= 0 should raise ArgumentError
|
5
|
+
|
6
|
+
Scenario Outline: Testing well initialized instance_variables
|
7
|
+
Given a SpanBarProcessor is initialized with "3", "3"
|
8
|
+
Then <instance_var> should be set to <value>
|
9
|
+
Examples:
|
10
|
+
| instance_var | value |
|
11
|
+
| @ticks | [] |
|
12
|
+
| @limit | 9 |
|
13
|
+
| @simpleMax | 0 |
|
14
|
+
| @simpleMin | Float::INFINITY |
|
15
|
+
| @simpleBar | [] |
|
16
|
+
| @simpleBars | [] |
|
17
|
+
| @intraday | false |
|
18
|
+
| @both | false |
|
19
|
+
| @simple | false |
|
20
|
+
|
21
|
+
#Scenario Outline: Testing methods and attr
|
22
|
+
#Given a SpanBarProcessor is initialized with "4", "3"
|
23
|
+
#Then it should respond to "<method>"
|
24
|
+
#Examples:
|
25
|
+
# | method |
|
26
|
+
# | add |
|
27
|
+
# | simpleBars |
|
28
|
+
# | create_strict_from |
|
29
|
+
#
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: Using #add
|
2
|
+
|
3
|
+
Scenario: Falsey input
|
4
|
+
Given a simple SpanBarProcessor is initialized with "3", "3"
|
5
|
+
Then it should raise ArgumentError when calling #add with less than 2 arguments
|
6
|
+
Then it should raise ArgumentError when calling #add and first argument is neither Integer nor Time
|
7
|
+
Then it should raise ArgumentError when calling #add and second argument is neither Numeric nor Nil
|
8
|
+
|
9
|
+
Scenario: Correct return values
|
10
|
+
Given a simple SpanBarProcessor is initialized with "3", "3"
|
11
|
+
Then calling #add with params 123 and nil should return nil
|
12
|
+
Then calling #add with params 123 and 2.5 should return false
|
13
|
+
|
14
|
+
Scenario: eesting a linear raising series
|
15
|
+
Given a simple SpanBarProcessor is initialized with "3", "1"
|
16
|
+
Then #add with params 1, 1 should return false
|
17
|
+
Then #add with params 2, 2 should return false
|
18
|
+
Then #add with params 3, 3 should return false
|
19
|
+
Then #add with params 4, 4 should return false
|
20
|
+
Then #add with params 5, 5 should return an Array
|
21
|
+
|
22
|
+
Scenario Outline: Running with reference data
|
23
|
+
Given a SpanBarProcessor is initialized with "<deviation>", "<ticksize>"
|
24
|
+
And a feeder with data from "<file>" is prepared
|
25
|
+
Then adding all data from file should not raise any error
|
26
|
+
|
27
|
+
Examples:
|
28
|
+
| file | deviation | ticksize |
|
29
|
+
| ./features/support/ref1.csv | 5 | 0.25 |
|
30
|
+
| ./features/support/ref1.csv | 8 | 0.1 |
|
31
|
+
| ./features/support/ref1.csv | 12 | 0.66 |
|
32
|
+
| ./features/support/ref2.csv | 5 | 1 |
|
33
|
+
| ./features/support/ref2.csv | 8 | 2 |
|
34
|
+
| ./features/support/ref2.csv | 12 | 5.5 |
|
35
|
+
| ./features/support/ref3.csv | 5 | 0.0000005 |
|
36
|
+
| ./features/support/ref3.csv | 8 | 0.000001 |
|
37
|
+
| ./features/support/ref3.csv | 12 | 0.00000025 |
|
38
|
+
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Feature: Initializiation of SpanBar
|
2
|
+
Scenario: Testing provided arguments during initialization
|
3
|
+
* a new simple SpanBar created without options should raise ArgumentError
|
4
|
+
* a new simple SpanBar created by SpanBarProcessor should not raise
|
5
|
+
|
6
|
+
Scenario Outline: Testing well initialized instance_variables
|
7
|
+
Given a valid simple SpanBar is created by SpanBarProcessor
|
8
|
+
Then <instance_var> should be set to <value>
|
9
|
+
Examples:
|
10
|
+
| instance_var | value |
|
11
|
+
| @strict | false |
|
12
|
+
| @type | :up |
|
13
|
+
| @open | 1 |
|
14
|
+
| @momentum | Float::INFINITY |
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
Scenario Outline: Testing methods and attr of SpanBar
|
19
|
+
Given a valid simple SpanBar is created by SpanBarProcessor
|
20
|
+
Then it should respond to "<method>"
|
21
|
+
Examples:
|
22
|
+
| method |
|
23
|
+
| inspect |
|
24
|
+
| to_human |
|
25
|
+
| to_a |
|
26
|
+
| valid? |
|
27
|
+
| path |
|
28
|
+
| momentum |
|
29
|
+
| split_for|
|
30
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Using spanbars on commandline
|
2
|
+
Scenario: When using bin/spanbars on the commandline without parameters
|
3
|
+
Given bin/spanbars is run on the commandline and neither parameters nor STDIN is given
|
4
|
+
#Then bin/spanbars should display help
|
5
|
+
|
6
|
+
Scenario Outline: Checking known input to produce known output
|
7
|
+
Given bin/spanbars is run with following parameters it should ouput
|
8
|
+
Then cat <input> | spanbars --both --ticksize <ticksize> --span <span> should produce <output>
|
9
|
+
Examples:
|
10
|
+
| input | ticksize | span | output |
|
11
|
+
| ref1 | 0.25 | 25 | ref1_out_0.25_25 |
|
12
|
+
| ref2 | 1 | 25 | ref2_out_1_25 |
|
13
|
+
| ref3 | 0.0000005 | 10 | ref3_out_0.0000005_10 |
|
14
|
+
|
15
|
+
Scenario: Checking whether false reference is recognized
|
16
|
+
Given bin/spanbars is run with following parameters it should ouput
|
17
|
+
Then 'cat ref3 | bin/spanbars --both --span 10 --ticksize 0.0000005' should not produce ref2_out_1_25
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require './lib/spanbar.rb'
|
2
|
+
require './lib/spanbarprocessor.rb'
|
3
|
+
|
4
|
+
Given "a new SpanBarProcessor created with span that is not Integer or <= 1 should raise ArgumentError" do
|
5
|
+
expect{ SpanBarProcessor.new(span: "t") }.to raise_error(ArgumentError)
|
6
|
+
expect{ SpanBarProcessor.new(span: 1.6) }.to raise_error(ArgumentError)
|
7
|
+
expect{ SpanBarProcessor.new(span: 1) }.to raise_error(ArgumentError)
|
8
|
+
end
|
9
|
+
|
10
|
+
Given "a new SpanBarProcessor created with a valid span but non-Numeric ticksize or <= 0 should raise ArgumentError" do
|
11
|
+
expect{ SpanBarProcessor.new(span: 2, ticksize: "foo")}.to raise_error(ArgumentError)
|
12
|
+
expect{ SpanBarProcessor.new(span: 2, ticksize: 0)}.to raise_error(ArgumentError)
|
13
|
+
expect{ SpanBarProcessor.new(span: 2, ticksize: -1.2)}.to raise_error(ArgumentError)
|
14
|
+
end
|
15
|
+
|
16
|
+
Given /^a SpanBarProcessor is initialized with "([^"]*)", "([^"]*)"$/ do |span, ticksize|
|
17
|
+
@s = SpanBarProcessor.new(span: span.to_i, ticksize: ticksize.to_f)
|
18
|
+
end
|
19
|
+
|
20
|
+
Given /^a simple SpanBarProcessor is initialized with "([^"]*)", "([^"]*)"$/ do |span, ticksize|
|
21
|
+
@s = SpanBarProcessor.new(span: span.to_i, ticksize: ticksize.to_f, simple: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
Then /^it should respond to "([^"]*)"$/ do |method|
|
26
|
+
expect(@s).to respond_to(method.to_sym)
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^([^\s]*) should be set to ([^\s]*)$/ do |var,value|
|
30
|
+
expect(@s.instance_variable_defined?(var.to_sym)).to be_truthy
|
31
|
+
res = nil
|
32
|
+
puts "#{var}---"
|
33
|
+
puts "#{value}---"
|
34
|
+
eval "res = @s.instance_variable_get(var.to_sym) == #{value}"
|
35
|
+
expect(res).to be_truthy
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Then "it should raise ArgumentError when calling #add with less than 2 arguments" do
|
2
|
+
expect{ @s.add }.to raise_error(ArgumentError)
|
3
|
+
expect{ @s.add(1)}.to raise_error(ArgumentError)
|
4
|
+
end
|
5
|
+
|
6
|
+
Then "it should raise ArgumentError when calling #add and first argument is neither Integer nor Time" do
|
7
|
+
expect{ @s.add("foo", "bar") }.to raise_error(ArgumentError)
|
8
|
+
expect{ @s.add(124, 1.22) }.not_to raise_error
|
9
|
+
expect{ @s.add(Time.now, 1.22) }.not_to raise_error
|
10
|
+
end
|
11
|
+
|
12
|
+
Then "it should raise ArgumentError when calling #add and second argument is neither Numeric nor Nil" do
|
13
|
+
expect{ @s.add(123, "foo") }.to raise_error(ArgumentError)
|
14
|
+
expect{ @s.add(123, 11234) }.not_to raise_error
|
15
|
+
expect{ @s.add(123, nil ) }.not_to raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^calling #add with params (\d+) and nil should return nil$/ do |timestamp|
|
19
|
+
expect(@s.add(timestamp, nil)).to be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^calling #add with params (\d+) and ([0-9.]+) should return false$/ do |timestamp, value|
|
23
|
+
expect(@s.add(timestamp, value.to_f)).to be(false)
|
24
|
+
end
|
25
|
+
|
26
|
+
Then /^#add with params (\d+), ([0-9.]+) should return false$/ do |timestamp, value|
|
27
|
+
expect(@s.add(timestamp, value.to_f)).to be(false)
|
28
|
+
end
|
29
|
+
|
30
|
+
Then /^#add with params (\d+), ([0-9.]+) should return an Array$/ do |timestamp, value|
|
31
|
+
result = @s.add(timestamp, value.to_f)
|
32
|
+
expect(result.class).to be(Array)
|
33
|
+
end
|
34
|
+
|
35
|
+
Given /^a feeder with data from "([^"]+)" is prepared$/ do |filename|
|
36
|
+
require 'csv'
|
37
|
+
@data = CSV.read(filename).map{|x| [ x[0].to_i, x[1].to_f] }
|
38
|
+
end
|
39
|
+
|
40
|
+
Then "adding all data from file should not raise any error" do
|
41
|
+
expect { @data.each {|d| @s.add(d[0],d[1]) } } .not_to raise_error
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Then "a new simple SpanBar created without options should raise ArgumentError" do
|
2
|
+
expect { SpanBar.new }.to raise_error(ArgumentError)
|
3
|
+
end
|
4
|
+
|
5
|
+
Then "a new simple SpanBar created by SpanBarProcessor should not raise" do
|
6
|
+
@p = SpanBarProcessor.new(simple: true)
|
7
|
+
expect { for i in (1..5); @p.add(i,i); end }.not_to raise_error
|
8
|
+
end
|
9
|
+
|
10
|
+
Given "a valid simple SpanBar is created by SpanBarProcessor" do
|
11
|
+
@p = SpanBarProcessor.new(simple: true); @s = true; i = 1;
|
12
|
+
while (not @s.is_a?(Array)) do @s = @p.add(i,i); i+=1; end
|
13
|
+
@s = @s[0]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Given /^bin\/spanbars is run on the commandline and neither parameters nor STDIN is given$/ do
|
2
|
+
end
|
3
|
+
|
4
|
+
Then /^bin\/spanbars should display help$/ do
|
5
|
+
expect{ system("bin/spanbars --help") }.to output(/usage/).to_stdout_from_any_process
|
6
|
+
end
|
7
|
+
|
8
|
+
Given /^bin\/spanbars is run with following parameters it should ouput$/ do
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^cat ([^ ]*) \| spanbars --both --ticksize ([^ ]*) --span ([^ ]*) should produce ([^ ]*)$/ do |input, ticksize, span, output|
|
12
|
+
inputfile = "features/support/#{input}.csv"
|
13
|
+
outputfile = "features/support/#{output}.csv"
|
14
|
+
result = `cat #{inputfile} | bin/spanbars --both --span #{span} --ticksize #{ticksize}`
|
15
|
+
reference = File.read(outputfile)
|
16
|
+
expect(result).to eq(reference)
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^'cat ([^ ]*) \| bin\/spanbars --both --span ([^ ]*) --ticksize ([^' ]*)' should not produce ([^"$ ]*)$/ do |input, span, ticksize, output|
|
20
|
+
inputfile = "features/support/#{input}.csv"
|
21
|
+
outputfile = "features/support/#{output}.csv"
|
22
|
+
result = `cat #{inputfile} | bin/spanbars --both --span #{span} --ticksize #{ticksize}`
|
23
|
+
reference = File.read(outputfile)
|
24
|
+
expect(result).not_to eq(reference)
|
25
|
+
end
|
26
|
+
|