spanbars 0.1.2beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|