are_we_there_yet 0.1.0 → 0.2.0

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.
data/README.md CHANGED
@@ -17,6 +17,19 @@ Usage is fairly simple:
17
17
  2. When running the specs pass the name of the class together with the location of your SQLite3 database, e.g:
18
18
  `spec -fAreWeThereYet:/path/to/db.sqlite3 spec`
19
19
 
20
+ Only passing tests are profiled.
21
+
22
+ ## Data Structure
23
+
24
+ The following data is stored in the database:
25
+
26
+ - runs (from v0.2.0 onwards) - this is to allow conclusive tracking of metrics against a specific run. Multiple runs close to one
27
+ may result in guesswork when determining which metrics belong to which run. v0.1.0 does not track this data, but v0.2.0 is backwards
28
+ compatible and can handle the reduced fidelity when dealing with a database created by v0.1.0.
29
+ - files - this represents the individual files containing the examples that are being run.
30
+ - examples - the individual examples themselves (one file has many examples)
31
+ - metrics - the run time per example (per run from v0.2.0 onwards) - one example has many metrics, one run has many metrics
32
+
20
33
  ## License
21
34
 
22
35
  Copyright (c) 2012 Rory McKinley
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{are_we_there_yet}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rory McKinley"]
@@ -6,6 +6,8 @@ class AreWeThereYet < Spec::Runner::Formatter::BaseFormatter
6
6
  @db = SQLite3::Database.new(where)
7
7
 
8
8
  create_tables
9
+
10
+ log_run
9
11
  end
10
12
 
11
13
  def example_started(example)
@@ -18,16 +20,26 @@ class AreWeThereYet < Spec::Runner::Formatter::BaseFormatter
18
20
 
19
21
  example_id = persist_example(db, example, location_id)
20
22
 
21
- db.execute(
22
- "INSERT INTO metrics(example_id, execution_time) VALUES(:example_id, :execution_time)",
23
- :example_id => db.last_insert_row_id,
24
- :execution_time => Time.now - @start
25
- )
23
+ persist_metric(db, example_id)
26
24
  end
27
25
  end
28
26
 
27
+ def close
28
+ @db.execute(
29
+ "UPDATE runs SET ended_at = :end_time WHERE id = :run_id",
30
+ :end_time => Time.now.strftime("%Y-%m-%d %H:%M:%S"),
31
+ :run_id => @run_id
32
+ ) if tracking_runs?
33
+ @db.close
34
+ end
35
+
29
36
  private
30
37
 
38
+ def log_run
39
+ @db.execute("INSERT INTO runs(id) VALUES(NULL)") if tracking_runs?
40
+ @run_id = @db.last_insert_row_id
41
+ end
42
+
31
43
  def persist_file(db, example)
32
44
  path = example.location.split(':').first
33
45
 
@@ -58,17 +70,39 @@ class AreWeThereYet < Spec::Runner::Formatter::BaseFormatter
58
70
  end
59
71
  end
60
72
 
73
+ def persist_metric(db, example_id)
74
+ if tracking_runs?
75
+ db.execute(
76
+ "INSERT INTO metrics(example_id, execution_time, run_id) VALUES(:example_id, :execution_time, :run_id)",
77
+ :example_id => db.last_insert_row_id,
78
+ :execution_time => Time.now - @start,
79
+ :run_id => @run_id
80
+ )
81
+ else
82
+ db.execute(
83
+ "INSERT INTO metrics(example_id, execution_time) VALUES(:example_id, :execution_time)",
84
+ :example_id => db.last_insert_row_id,
85
+ :execution_time => Time.now - @start
86
+ )
87
+ end
88
+ end
89
+
61
90
  def create_tables
62
91
  existing_tables = @db.execute("SELECT name FROM sqlite_master")
63
92
 
64
93
  if existing_tables.empty?
65
94
  @db.transaction do |db|
95
+ db.execute("CREATE TABLE runs(id INTEGER PRIMARY KEY, started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ended_at TIMESTAMP)")
66
96
  db.execute("CREATE TABLE files(id INTEGER PRIMARY KEY, path VARCHAR(255))")
67
97
  db.execute("CREATE INDEX path ON files (path)")
68
98
  db.execute("CREATE TABLE examples(id INTEGER PRIMARY KEY, file_id INTEGER, description TEXT)")
69
99
  db.execute("CREATE INDEX file_description ON examples (file_id, description)")
70
- db.execute("CREATE TABLE metrics(id INTEGER PRIMARY KEY, example_id INTEGER, execution_time FLOAT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")
100
+ db.execute("CREATE TABLE metrics(id INTEGER PRIMARY KEY, example_id INTEGER, execution_time FLOAT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, run_id INTEGER )")
71
101
  end
72
102
  end
73
103
  end
104
+
105
+ def tracking_runs?
106
+ @tracking_runs ||= @db.execute("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'runs'").any?
107
+ end
74
108
  end
@@ -21,6 +21,7 @@ describe AreWeThereYet do
21
21
  table_exists?(@db_name, 'files').should be_true
22
22
  table_exists?(@db_name, 'examples').should be_true
23
23
  table_exists?(@db_name, 'metrics').should be_true
24
+ table_exists?(@db_name, 'runs').should be_true
24
25
  end
25
26
 
26
27
  it "creates the necessary indexes" do
@@ -52,6 +53,31 @@ describe AreWeThereYet do
52
53
 
53
54
  connection.execute2("SELECT name FROM sqlite_master").size.should == 1 # Execute2 lists fields - size 1 means empty response
54
55
  end
56
+
57
+ it "logs the start of a spec run" do
58
+ AreWeThereYet.new({},@db_name)
59
+ connection = SQLite3::Database.new(@db_name)
60
+
61
+ run = connection.get_first_row("SELECT id, started_at FROM runs")
62
+ run.should_not be_nil
63
+ run[1].should_not be_nil
64
+ end
65
+
66
+ it "does not log the start of a spec run if there is no table in the database" do
67
+ # This to maintain backwards-compatibility with DBs created by v0.1.0
68
+ connection = SQLite3::Database.new(@db_name)
69
+ connection.stub(:execute) do |arg|
70
+ if arg =~ /CREATE TABLE runs/
71
+ # Do nothing
72
+ else
73
+ connection.execute2(arg)
74
+ []
75
+ end
76
+ end
77
+ SQLite3::Database.should_receive(:new).and_return(connection)
78
+
79
+ expect { AreWeThereYet.new({},@db_name) }.should_not raise_error
80
+ end
55
81
  end
56
82
 
57
83
  describe "logging a metric for a new file" do
@@ -94,15 +120,31 @@ describe AreWeThereYet do
94
120
  @awty.example_passed(@mock_example)
95
121
 
96
122
  connection = SQLite3::Database.new(@db_name)
123
+ run = connection.get_first_row("SELECT id FROM runs")
124
+ run_id = run.first
125
+
97
126
  example = connection.get_first_row("SELECT id FROM examples")
98
127
  example_id = example.first
99
128
 
100
129
  Time.stub!(:now)
101
- metrics = connection.execute("SELECT id, example_id, execution_time, created_at FROM metrics")
130
+ metrics = connection.execute("SELECT id, example_id, execution_time, created_at, run_id FROM metrics")
102
131
  metrics.size.should == 1
103
132
  metrics.first[1].should == example_id
104
133
  metrics.first[2].should == end_time - start_time
105
134
  metrics.first[3].should_not be_nil
135
+ metrics.first[4].should == run_id
136
+ end
137
+
138
+ it "does not link the metric to a run if the run table does not exist" do
139
+ # To maintain compatibility with version 0.1.0
140
+ AreWeThereYet.any_instance.should_receive(:tracking_runs?).and_return(false)
141
+
142
+ connection = SQLite3::Database.new(@db_name)
143
+ connection.execute("DROP TABLE metrics")
144
+ connection.execute("CREATE TABLE metrics(id INTEGER PRIMARY KEY, example_id INTEGER, execution_time FLOAT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")
145
+
146
+ @awty.example_started(@mock_example)
147
+ expect { @awty.example_passed(@mock_example) }.should_not raise_error
106
148
  end
107
149
  end
108
150
 
@@ -170,4 +212,33 @@ describe AreWeThereYet do
170
212
  connection.execute("SELECT * FROM examples").should be_empty
171
213
  end
172
214
  end
215
+
216
+ describe "closing" do
217
+ before(:each) do
218
+ @awty = AreWeThereYet.new({}, @db_name)
219
+ @mock_example = mock(Spec::Example::ExampleProxy, :location => "/path/to/spec", :description => "blaah")
220
+ @awty.example_started(@mock_example)
221
+ end
222
+
223
+ it "closes the connection to the database" do
224
+ SQLite3::Database.any_instance.should_receive(:close)
225
+ @awty.close
226
+ end
227
+
228
+ it "updates the end time value for the relevant run" do
229
+ @awty.close
230
+
231
+ connection = SQLite3::Database.new(@db_name)
232
+ run = connection.get_first_row('SELECT ended_at FROM runs')
233
+ run.first.should_not be_nil
234
+ end
235
+
236
+ it "does not update the run if runs are not being tracked" do
237
+ connection = SQLite3::Database.new(@db_name)
238
+ connection.execute("DROP TABLE runs")
239
+ AreWeThereYet.any_instance.should_receive(:tracking_runs?).and_return(false)
240
+
241
+ expect { @awty.close }.should_not raise_error
242
+ end
243
+ end
173
244
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: are_we_there_yet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
10
  segments_generated: true
11
- version: 0.1.0
11
+ version: 0.2.0
12
12
  platform: ruby
13
13
  authors:
14
14
  - Rory McKinley