fixpoints 0.1.0 → 0.2.1
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 +4 -4
- data/.gitignore +2 -0
- data/Gemfile.lock +2 -1
- data/README.md +117 -27
- data/lib/fixpoint.rb +11 -13
- data/lib/fixpoint_test_helpers.rb +62 -0
- data/lib/fixpoints.rb +2 -1
- data/lib/fixpoints/version.rb +1 -1
- data/lib/incremental_fixpoint.rb +3 -61
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0a554a0fdd5ab6cb391f8fc79bfce70198c97acc31d56f055c5eba6df02a589
|
4
|
+
data.tar.gz: 8b547d25f541c7e76cf0cb3e766fb189c1f01776532dab2530f8f48ef59e475e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b234ac70213d6af97dcd37bd808429e3e1b970e29ca1712b74b73f5808992c10807bcd8b2743f47ded07e09a0fdf814e09d3452a13d98dc4cd465d12ac35793d
|
7
|
+
data.tar.gz: 1c8a83b052a6c1668301cab7e05e1c141415970fad258ce0a2611216f20b98d6ec945231ebe42e0b1773367c35cf9b6d6fb1f545f269345097e3e46d7f30a905
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,46 +2,138 @@
|
|
2
2
|
|
3
3
|
Fixpoints enables saving, restoring and comparing the database state before & after tests.
|
4
4
|
|
5
|
+
This gem came about during my time at [Netskin GmbH](https://www.netskin.com/en). Check it out, we do great (Rails) work there.
|
6
|
+
|
5
7
|
## Motivation
|
6
8
|
|
7
|
-
|
9
|
+
When running behavior tests, we seed the database with a defined snapshot called fixpoint.
|
10
|
+
We do run the behavior test and save the resulting database state as another fixpoint.
|
11
|
+
This method allows testing complex business processes in legacy applications without having to implement fixtures/factories upfront.
|
12
|
+
By building one fixpoint on top of another, we can ensure that the process chain works without any gaps.
|
13
|
+
Comparing each resulting database state at the end of a test with a previously recorded state ensures that refactoring did not have unintended side effects.
|
14
|
+
|
15
|
+
**Advantages**
|
16
|
+
|
17
|
+
- No need to write fixtures or factories
|
18
|
+
- discover which records were created/changed by the test’s actions by reading the fixpoint file (YAML)
|
19
|
+
- get notified about differences in database state (i.e. unintended side effects) after refactoring something
|
20
|
+
- allow version control to save the "ground truth" at the end of a test
|
21
|
+
|
22
|
+
Please check out the full article: [Behavior-Driven Test Data](https://tomrothe.de/posts/behaviour-driven-test-data.html).
|
8
23
|
|
9
|
-
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add this line to your application's Gemfile: `gem 'fixpoints'` and make sure to add:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
# rails_helper.rb
|
30
|
+
RSpec.configure do |config|
|
31
|
+
# ...
|
32
|
+
config.include FixpointTestHelpers
|
33
|
+
end
|
34
|
+
```
|
10
35
|
|
11
36
|
## Usage
|
12
37
|
|
13
|
-
|
38
|
+
We save the fixpoint (database snapshot) after the test. Other tests can build on them.
|
14
39
|
|
15
|
-
|
40
|
+
A fixpoint is a snapshot of the database contents as YAML file.
|
41
|
+
It is saved to the `spec/fixpoints` folder.
|
42
|
+
The file contains a mapping of table names to a list if their records.
|
43
|
+
Empty tables are stripped from files.
|
16
44
|
|
45
|
+
**Order & Bootstrapping** We need to mind the order though.
|
46
|
+
When bootstrapping (when there is no fixpoints saved to the disk yet), we need to make sure that all tests that depend on a certain fixpoint run _after_ it was stored.
|
47
|
+
In a single RSpec file, you can use the order in which the tests are defined (`RSpec.describe 'MyFeature', order: :defined do`).
|
48
|
+
However, tests in groups might follow a slightly different order (see [RSpec Docs](https://relishapp.com/rspec/rspec-core/docs/configuration/overriding-global-ordering))
|
17
49
|
|
18
50
|
```ruby
|
19
|
-
|
20
|
-
it 'registers a user' do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
51
|
+
RSpec.describe 'User Flow', order: :defined do # !!! mind the order here !!!
|
52
|
+
it 'registers a user' do
|
53
|
+
visit new_user_path
|
54
|
+
fill_in 'Name', with: 'Tom'
|
55
|
+
click_on 'Save'
|
56
|
+
|
57
|
+
store_fixpoint_unless_present :registered_user
|
58
|
+
# creates a YAML file containing all records (/spec/fixpoints/registred_user.yml)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'posts an item' do
|
62
|
+
restore_fixpoint :registered_user
|
63
|
+
|
64
|
+
user = User.find_by(name: 'Hans')
|
65
|
+
visit new_item_path(user)
|
66
|
+
fill_in 'Item', with: '...'
|
67
|
+
click_on 'Post'
|
68
|
+
|
69
|
+
compare_fixpoint(:item_posted, store_fixpoint_and_fail: true)
|
70
|
+
# compares the database state with the previously saved fixpoint and
|
71
|
+
# raises if there is a difference. when there is no previous fixpoint,
|
72
|
+
# it writes the fixpoint and fails the test (so it can be re-run)
|
73
|
+
end
|
27
74
|
end
|
75
|
+
```
|
76
|
+
|
77
|
+
**Changes** If you did a lot of changes to a test, you can remove a fixpoint file from its directory.
|
78
|
+
It will be recreated when the test producing it runs again.
|
79
|
+
Don't forget re-running the tests based on it because their fixpoints might have to change too.
|
80
|
+
Example: You need to add something to the database's `seeds.rb`. All subsequent fixpoints are missing the required entry.
|
81
|
+
To update all fixpoints, just remove the whole `spec/fixpoints` folder and re-run all tests. Now all fixpoints should be updated.
|
82
|
+
Be careful though, don't just remove the fixpoints if you are not sure what is going on.
|
83
|
+
A change in a fixpoint might point to an unintended change in code.
|
28
84
|
|
29
|
-
|
85
|
+
We need to be be careful to use `let` and `let!` with factories.
|
86
|
+
Records might be created twice when using create in there (once by the fixpoint and once by the factory).
|
87
|
+
|
88
|
+
**Ignoring columns** Often you might want to add more columns to ignore (e.g. login time stamps):
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
let(:ignored_fixpoint_columns) { [:updated_at, :created_at, users: [:last_login_at] }
|
92
|
+
# ignores timestamps for all tables, and last_login_at for the users table
|
93
|
+
|
94
|
+
it 'logs in' do
|
30
95
|
restore_fixpoint :registered_user
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
fill_in 'Item', with: '...'
|
35
|
-
click_on 'Post'
|
36
|
-
|
37
|
-
compare_fixpoint(:posted_item, ignore_columns: [:release_date], store_fixpoint_and_fail: true)
|
38
|
-
# compares the database state with the previously saved fixpoint and
|
39
|
-
# raises if there is a difference. when there is no previous fixpoint,
|
40
|
-
# it writes it and fails the test (so it can be re-run)
|
96
|
+
# ...
|
97
|
+
compare_fixpoint(:registered_user, ignored_fixpoint_columns)
|
98
|
+
# asserts that there is no change
|
41
99
|
end
|
42
100
|
```
|
43
101
|
|
44
|
-
|
102
|
+
**Incremental** By the default the `FixpointTestHelpers` use the `IncrementalFixpoint` instead of the more verbose `Fixpoint` version.
|
103
|
+
This means that only changes are saved to the YAML file.
|
104
|
+
In order to achieve this, we must make sure that we let the store function know who daddy is.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
it 'posts an item' do
|
108
|
+
restore_fixpoint :registered_user
|
109
|
+
# ...
|
110
|
+
compare_fixpoint(fixname, store_fixpoint_and_fail: true, parent_fixname: :registered_user)
|
111
|
+
# now only changes to compared to the previous fixpoint are stored
|
112
|
+
# instead of using the name of the last restored fixpoint, you can also use `:last_restored`
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
**Multiple Databases** If an application uses multiple databases, you can use the optional `connection` parameter
|
117
|
+
to specify the database connection to use.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
it 'posts an item' do
|
121
|
+
restore_fixpoint :registered_user, connection: ActiveRecord::Base.connection
|
122
|
+
# ...
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
## Limitations & Known issues
|
127
|
+
|
128
|
+
- The records in tables are ordered by their id.
|
129
|
+
If there is no id for a table, we use database's order (what the SELECT query returns).
|
130
|
+
This order may be instable.
|
131
|
+
- We do not clean the database after each test, depending on your cleaning strategy (e.g. transaction), we might leak primary key sequence counters from one test to another.
|
132
|
+
If you have problems try running `Fixpoint.reset_pk_sequences!` and create am issue, so we can investigate.
|
133
|
+
- Under certain conditions you may get `duplicate key value violates unique constraint` because the primary key sequences are not updated correctly.
|
134
|
+
If this happens, just add a `Fixpoint.reset_pk_sequences!` at the beginning of your test. We need to dig a little deeper here at some point...
|
135
|
+
|
136
|
+
# Development
|
45
137
|
|
46
138
|
```bash
|
47
139
|
docker run --rm -ti -v (pwd):/app -w /app ruby:2.7 bash
|
@@ -53,11 +145,9 @@ gem build
|
|
53
145
|
gem install fixpoints-0.1.0.gem
|
54
146
|
pry -r fixpoints
|
55
147
|
gem uninstall fixpoints
|
148
|
+
gem push fixpoints
|
56
149
|
```
|
57
150
|
|
58
|
-
|
59
|
-
## Development
|
60
|
-
|
61
151
|
## Contributing
|
62
152
|
|
63
153
|
Bug reports and pull requests are welcome on GitHub at https://github.com/motine/fixpoints.
|
data/lib/fixpoint.rb
CHANGED
@@ -45,8 +45,8 @@ class Fixpoint
|
|
45
45
|
end
|
46
46
|
|
47
47
|
# Creates a Fixpoint from the database contents. Empty tables are skipped.
|
48
|
-
def from_database
|
49
|
-
new(read_database_records)
|
48
|
+
def from_database(conn)
|
49
|
+
new(read_database_records(conn))
|
50
50
|
end
|
51
51
|
|
52
52
|
def remove(fixname)
|
@@ -56,7 +56,7 @@ class Fixpoint
|
|
56
56
|
# reset primary key sequences for all tables
|
57
57
|
# useful when tests sometimes run before the storing the first fixpoint.
|
58
58
|
# these test might have incremented the id sequence already, so the ids in the fixpoints chance (which leads to differences).
|
59
|
-
def reset_pk_sequences!
|
59
|
+
def reset_pk_sequences!(conn)
|
60
60
|
return unless conn.respond_to?(:reset_pk_sequence!)
|
61
61
|
conn.tables.each { |table_name| conn.reset_pk_sequence!(table_name) }
|
62
62
|
end
|
@@ -69,10 +69,6 @@ class Fixpoint
|
|
69
69
|
File.join(fspath, "#{fixname}.yml")
|
70
70
|
end
|
71
71
|
|
72
|
-
def conn
|
73
|
-
ActiveRecord::Base.connection
|
74
|
-
end
|
75
|
-
|
76
72
|
protected
|
77
73
|
|
78
74
|
def fixpoints_path
|
@@ -85,17 +81,21 @@ class Fixpoint
|
|
85
81
|
File.join(spec_path, FIXPOINT_FOLDER)
|
86
82
|
end
|
87
83
|
|
88
|
-
def read_database_records
|
84
|
+
def read_database_records(conn)
|
89
85
|
# adapted from: https://yizeng.me/2017/07/16/generate-rails-test-fixtures-yaml-from-database-dump/
|
90
86
|
tables = conn.tables
|
91
87
|
tables.reject! { |table_name| TABLES_TO_SKIP.include?(table_name) }
|
92
88
|
|
93
89
|
tables.each_with_object({}) do |table_name, acc|
|
94
|
-
result = conn.select_all("SELECT * FROM #{table_name}")
|
90
|
+
result = conn.select_all("SELECT * FROM #{conn.quote_table_name(table_name)}")
|
95
91
|
next if result.count.zero?
|
96
92
|
|
97
93
|
rows = result.to_a
|
98
94
|
rows.sort_by! { |row| row['id'] } if result.columns.include?('id') # let's make the order of items stable
|
95
|
+
# fix jsonb columns by re-parsing them, so they are not saved as string to the yaml file
|
96
|
+
jsonb_columns = result.column_types.select { |_, col_type| col_type.type == :jsonb }.collect { |col_name, _| col_name }
|
97
|
+
rows.collect! { |row| jsonb_columns.each {|jcol| row[jcol] = JSON.parse(row[jcol]) }; row }
|
98
|
+
|
99
99
|
acc[table_name] = rows
|
100
100
|
end
|
101
101
|
end
|
@@ -107,7 +107,7 @@ class Fixpoint
|
|
107
107
|
@records_in_tables = records_in_tables
|
108
108
|
end
|
109
109
|
|
110
|
-
def load_into_database
|
110
|
+
def load_into_database(conn)
|
111
111
|
# Here some more pointers on implementation details of fixtures:
|
112
112
|
# - https://github.com/rails/rails/blob/2998672fc22f0d5e1a79a29ccb60d0d0e627a430/activerecord/lib/active_record/fixtures.rb#L612
|
113
113
|
# - http://api.rubyonrails.org/v5.2.4/classes/ActiveRecord/FixtureSet.html#method-c-create_fixtures
|
@@ -123,7 +123,7 @@ class Fixpoint
|
|
123
123
|
|
124
124
|
# actually insert
|
125
125
|
conn.insert_fixtures_set(@records_in_tables)
|
126
|
-
self.class.reset_pk_sequences!
|
126
|
+
self.class.reset_pk_sequences!(conn)
|
127
127
|
end
|
128
128
|
|
129
129
|
def save_to_file(fixname)
|
@@ -146,8 +146,6 @@ class Fixpoint
|
|
146
146
|
|
147
147
|
protected
|
148
148
|
|
149
|
-
delegate :conn, to: :class
|
150
|
-
|
151
149
|
def contents_for_file
|
152
150
|
YAML.dump(@records_in_tables)
|
153
151
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Helper methods to be included into RSpec
|
2
|
+
module FixpointTestHelpers
|
3
|
+
def restore_fixpoint(fixname, connection: default_connection)
|
4
|
+
@last_restored = fixname
|
5
|
+
IncrementalFixpoint.from_file(fixname).load_into_database(connection)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Compares the fixpoint with the records in the database.
|
9
|
+
# If there is no such fixpoint yet, it will write a new one to the file system.
|
10
|
+
# The latter is useful if the fixpoint was deleted to accommodate changes to it (see example in class description).
|
11
|
+
#
|
12
|
+
# +tables_to_compare+ can either be +:all+ or a list of table names (e.g. ['users', 'posts'])
|
13
|
+
# +ignored_columns+ see Fixnum#records_for_table
|
14
|
+
# +store_fixpoint_and_fail+ when given and the fixpoint does not already exist, a new fixpoint is created an the test will be marked pending/failed
|
15
|
+
# +parent_fixname+ when storing a new fixpoint, use this as parent fixpoint (you can specify `:last_restored` then the last given to restore_fixpoint is used; not thread safe)
|
16
|
+
# ---
|
17
|
+
# If we refactor this to a gem, we should rely on rspec (e.g. use minitest or move comparison logic to Fixpoint class).
|
18
|
+
# Anyhow, we keep it like this for now, because the expectations give much nicer output than the minitest assertions.
|
19
|
+
def compare_fixpoint(fixname, ignored_columns=[:updated_at, :created_at], tables_to_compare: :all, store_fixpoint_and_fail: false, parent_fixname: nil, connection: default_connection)
|
20
|
+
if !IncrementalFixpoint.exists?(fixname)
|
21
|
+
if store_fixpoint_and_fail
|
22
|
+
store_fixpoint(fixname, parent_fixname, connection: connection)
|
23
|
+
pending("Fixpoint \"#{fixname}\" did not exist yet. Skipping comparison, but created fixpoint from database. Try re-running the test.")
|
24
|
+
fail
|
25
|
+
else
|
26
|
+
raise Fixpoint::Error, "Fixpoint #{fixname} does not exist"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
database_fp = IncrementalFixpoint.from_database(nil, connection)
|
31
|
+
fixpoint_fp = IncrementalFixpoint.from_file(fixname)
|
32
|
+
|
33
|
+
tables_to_compare = (database_fp.table_names + fixpoint_fp.table_names).uniq if tables_to_compare == :all
|
34
|
+
tables_to_compare.each do |table_name|
|
35
|
+
db_records = database_fp.records_for_table(table_name, ignored_columns)
|
36
|
+
fp_records = fixpoint_fp.records_for_table(table_name, ignored_columns)
|
37
|
+
|
38
|
+
# if a table is present in a fixpoint, there must be records in it because empty tables are stripped from fixpoints
|
39
|
+
expect(db_records).not_to be_empty, "#{table_name} not in database, but in fixpoint"
|
40
|
+
expect(fp_records).not_to be_empty, "#{table_name} not in fixpoint, but in database"
|
41
|
+
# we assume that the order of records returned by SELECT is stable (so we do not do any sorting)
|
42
|
+
expect(db_records).to eq(fp_records), "Database records for table \"#{table_name}\" did not match fixpoint \"#{fixname}\". Consider removing the fixpoint and re-running the test if the change is intended."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# it is not a good idea to overwrite the fixpoint each time because timestamps may change (which then shows up in version control).
|
47
|
+
# Hence we only provide a method to write to it if it does not exist.
|
48
|
+
def store_fixpoint_unless_present(fixname, parent_fixname = nil, connection: default_connection)
|
49
|
+
store_fixpoint(fixname, parent_fixname, connection: connection) unless IncrementalFixpoint.exists?(fixname)
|
50
|
+
end
|
51
|
+
|
52
|
+
# +parent_fixname+ when given, only the (incremental) changes to the parent are saved
|
53
|
+
# please see store_fixpoint_unless_present for note on why not to use this method
|
54
|
+
def store_fixpoint(fixname, parent_fixname = nil, connection: default_connection)
|
55
|
+
parent_fixname = @last_restored if parent_fixname == :last_restored
|
56
|
+
IncrementalFixpoint.from_database(parent_fixname, connection).save_to_file(fixname)
|
57
|
+
end
|
58
|
+
|
59
|
+
private def default_connection
|
60
|
+
ActiveRecord::Base.connection
|
61
|
+
end
|
62
|
+
end
|
data/lib/fixpoints.rb
CHANGED
@@ -3,7 +3,8 @@ require_relative "fixpoint_diff"
|
|
3
3
|
|
4
4
|
require_relative "fixpoint"
|
5
5
|
require_relative "incremental_fixpoint"
|
6
|
+
require_relative "fixpoint_test_helpers"
|
6
7
|
|
7
|
-
if defined?(RSpec)
|
8
|
+
if defined?(RSpec) && RSpec.respond_to?(:configure)
|
8
9
|
RSpec.configure { |c| c.add_setting :fixpoints_path }
|
9
10
|
end
|
data/lib/fixpoints/version.rb
CHANGED
data/lib/incremental_fixpoint.rb
CHANGED
@@ -33,11 +33,11 @@ class IncrementalFixpoint < Fixpoint
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Creates a Fixpoint from the database contents. Empty tables are skipped.
|
36
|
-
def self.from_database(parent_fixname=nil)
|
37
|
-
return super() if parent_fixname.nil?
|
36
|
+
def self.from_database(parent_fixname=nil, conn)
|
37
|
+
return super(conn) if parent_fixname.nil?
|
38
38
|
|
39
39
|
parent = from_file(parent_fixname)
|
40
|
-
changes_in_tables = FixpointDiff.extract_changes(parent.records_in_tables, read_database_records)
|
40
|
+
changes_in_tables = FixpointDiff.extract_changes(parent.records_in_tables, read_database_records(conn))
|
41
41
|
new(changes_in_tables, parent_fixname)
|
42
42
|
end
|
43
43
|
|
@@ -49,61 +49,3 @@ class IncrementalFixpoint < Fixpoint
|
|
49
49
|
return YAML.dump(file_contents)
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
# Helper methods to be included into RSpec
|
54
|
-
module FixpointTestHelpers
|
55
|
-
def restore_fixpoint(fixname)
|
56
|
-
IncrementalFixpoint.from_file(fixname).load_into_database
|
57
|
-
end
|
58
|
-
|
59
|
-
# Compares the fixpoint with the records in the database.
|
60
|
-
# If there is no such fixpoint yet, it will write a new one to the file system.
|
61
|
-
# The latter is useful if the fixpoint was deleted to accommodate changes to it (see example in class description).
|
62
|
-
#
|
63
|
-
# +tables_to_compare+ can either be +:all+ or a list of table names (e.g. ['users', 'posts'])
|
64
|
-
# +ignored_columns+ see Fixnum#records_for_table
|
65
|
-
# +not_exists_handler+ when given and the fixpoint does not exists, it will be called with the fixname as argument
|
66
|
-
#
|
67
|
-
# ---
|
68
|
-
# If we refactor this to a gem, we should rely on rspec (e.g. use minitest or move comparison logic to Fixpoint class).
|
69
|
-
# Anyhow, we keep it like this for now, because the expectations give much nicer output than the minitest assertions.
|
70
|
-
def compare_fixpoint(fixname, ignored_columns=[:updated_at, :created_at], tables_to_compare=:all, ¬_exists_handler)
|
71
|
-
if !IncrementalFixpoint.exists?(fixname)
|
72
|
-
not_exists_handler.call(fixname) if not_exists_handler
|
73
|
-
return
|
74
|
-
end
|
75
|
-
|
76
|
-
database_fp = IncrementalFixpoint.from_database
|
77
|
-
fixpoint_fp = IncrementalFixpoint.from_file(fixname)
|
78
|
-
|
79
|
-
tables_to_compare = (database_fp.table_names + fixpoint_fp.table_names).uniq if tables_to_compare == :all
|
80
|
-
tables_to_compare.each do |table_name|
|
81
|
-
db_records = database_fp.records_for_table(table_name, ignored_columns)
|
82
|
-
fp_records = fixpoint_fp.records_for_table(table_name, ignored_columns)
|
83
|
-
|
84
|
-
# if a table is present in a fixpoint, there must be records in it because empty tables are stripped from fixpoints
|
85
|
-
expect(db_records).not_to be_empty, "#{table_name} not in database, but in fixpoint"
|
86
|
-
expect(fp_records).not_to be_empty, "#{table_name} not in fixpoint, but in database"
|
87
|
-
# we assume that the order of records returned by SELECT is stable (so we do not do any sorting)
|
88
|
-
expect(db_records).to eq(fp_records), "Database records for table \"#{table_name}\" did not match fixpoint \"#{fixname}\". Consider removing the fixpoint and re-running the test if the change is intended."
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def store_fixpoint_and_fail(fixname, parent_fixname = nil)
|
93
|
-
store_fixpoint(fixname, parent_fixname)
|
94
|
-
pending("Fixpoint \"#{fixname}\" did not exist yet. Skipping comparison, but created fixpoint from database")
|
95
|
-
fail
|
96
|
-
end
|
97
|
-
|
98
|
-
# it is not a good idea to overwrite the fixpoint each time because timestamps may change (which then shows up in version control).
|
99
|
-
# Hence we only provide a method to write to it if it does not exist.
|
100
|
-
def store_fixpoint_unless_present(fixname, parent_fixname = nil)
|
101
|
-
store_fixpoint(fixname, parent_fixname) unless IncrementalFixpoint.exists?(fixname)
|
102
|
-
end
|
103
|
-
|
104
|
-
# +parent_fixname+ when given, only the (incremental) changes to the parent are saved
|
105
|
-
# please see store_fixpoint_unless_present for note on why not to use this method
|
106
|
-
def store_fixpoint(fixname, parent_fixname = nil)
|
107
|
-
IncrementalFixpoint.from_database(parent_fixname).save_to_file(fixname)
|
108
|
-
end
|
109
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fixpoints
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Rothe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- fixpoints.gemspec
|
56
56
|
- lib/fixpoint.rb
|
57
57
|
- lib/fixpoint_diff.rb
|
58
|
+
- lib/fixpoint_test_helpers.rb
|
58
59
|
- lib/fixpoints.rb
|
59
60
|
- lib/fixpoints/version.rb
|
60
61
|
- lib/incremental_fixpoint.rb
|