testing_your_legacy 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cca438f1b58bc6facde234da7667c460a5417abd
4
+ data.tar.gz: b75b0f785770a5c168928c1587273c3b17c7e0af
5
+ SHA512:
6
+ metadata.gz: 1f97630931260738a514822892a456f91f49f987a37f0975d86578e84c780d7fc8be3afb9fd48d4b4b1eb59f0b671e781fe96982b2496a0a0fed7ebbe7160e2e
7
+ data.tar.gz: e61b9b77be2429bea963ed9191b830a435fbf0da29a26883b064801cf19ee44b68196165b1fbe6bc825615203cafd6cc15474368d48ef75c3a90291835722fd9
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in your_legacy_tests.gemspec
4
+ gemspec
5
+
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ testing_your_legacy (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.8.3)
10
+ rake (10.4.2)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bundler (~> 1.10)
17
+ minitest
18
+ rake (~> 10.0)
19
+ testing_your_legacy!
20
+
21
+ BUNDLED WITH
22
+ 1.10.6
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Timothy Nordloh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # YourLegacyTests
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'your_legacy_tests'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install your_legacy_tests
18
+
19
+ ## Usage
20
+
21
+
22
+ This gem should be used by people who have inherited a legacy application which lacks any tests, but has been running in production for a while. It uses Sumo Logic to find the most frequently used urls in an application, and then generates tests for those urls.
23
+
24
+ To run, execute the command:
25
+
26
+ `tests_via_sumo [-c or --count <count>] [-s or --source_category <category>]`
27
+
28
+ source_category defaults to a * .
29
+
30
+ Count defaults to 25, and controls the number of tests generated.
31
+
32
+ Results are generated on stdout, for maximum flexibility on where the tests are placed in the Rails application.
33
+
34
+
35
+ ## Caveats
36
+
37
+ Since Sumo Logic is nice enough to process logs for free, for smaller users, I'm releasing this gem with heavy dependence on Sumo's query function, for now. I plan on adding hooks to allow it to be more useful for processing logfiles without relying on Sumo for summing up the number of visits per page, ordering them from greatest to smallest, and parsing data out of the logfiles.
38
+
39
+ ### Prerequisites
40
+
41
+ Currently, this gem requires an active account with sumologic, and that you read your logfiles into sumologic. It then uses their api to aggregate the results, and create tests, based on frequency.
42
+
43
+ After reading log files with Sumo, run the sumo_sum command. It will prompt you to fill in the ~/.sumo_creds file, with your credentials, if you haven't already. Otherwise, it should parse your sumo logs, and return a list of tests to your command line, which you can pipe into a test file of your choise.
44
+
45
+ All of the tests are initially set to `skip`, so that you can enable them one at a time. Start at the first test, which is the most-visited link, and try to run it. It may need to have some prerequisites filled in; for example, perhaps it requires that the user be logged in, which may require you to create a relevant fixture, and ensure that a login url is called first.
46
+
47
+
48
+ #### Examples
49
+
50
+ These examples assume no real knowledge on building tests, other than the ability to run the `rake test` command; it is a summary of the things I wish I knew, when I tried to figure out how to test my legacy application, so if you are already familiar with writing tests, you may want to just skim this section.
51
+
52
+
53
+
54
+ #### Example 1: Base url test
55
+
56
+ I took the output from `tests_via_sumo`, and appended them to the `./test/integration/user_stories_test.rb` file.
57
+
58
+ Modifying the auto-generated test to work for you:
59
+
60
+ ```ruby
61
+ test "visit /" do
62
+ skip
63
+ #this url was visited 1647 times
64
+ get '/'
65
+ assert_response :success
66
+ end
67
+ ```
68
+
69
+ After uncommenting the `skip`, and running `rake test`, you might see something like:
70
+ ```
71
+ 1) Failure:
72
+ UserStoriesTest#test_visit_/ [/my_app/test/integration/user_stories_test.rb:96]:
73
+ Expected response to be a <success>, but was <302>
74
+ ```
75
+
76
+ This indicates that this url was redirected
77
+
78
+ You can then go to the production site, and verify that visit always results in a redirect, and modify the test accordingly. Also, you can add checks against the page content/type, perhaps by adding an `assert_content :index`, or whatever is appropriate. Also, the auto-generated name is a placeholder; rename it, once you understand the context.
79
+
80
+ After the test is cleaned up, it may look more like this:
81
+
82
+ ```ruby
83
+ test "visit home url, ensure it redirects to index" do
84
+ get '/'
85
+ assert_response :redirect
86
+ assert_template :index
87
+ end
88
+ ```
89
+
90
+ Once you have this one test perfected, you will have the most visited part of the site tested, and you can move to the next test.
91
+
92
+
93
+ Wow, that was easy, wasn't it? Unfortunately, building tests on a legacy application is rarely a simple matter, and you may have to go prospecting deep into the application to make a test work. Hopefully, using logs as a guide will help to create the most informative, useful tests first, and give us an idea of what setup requirements we will need for many other tests.
94
+
95
+ #### Example 2: Url requiring a login
96
+
97
+ This example walks through the process of building a test with several setup requirements. I'm going to break the setup into separate methods, which I can hopefully be reused other tests.
98
+
99
+ This test, as generated, doesn't work:
100
+ ```ruby
101
+ test "visit /user/profile/:id" do
102
+ skip
103
+ #this url was visited 424 times
104
+ get '/user/profile/:id'
105
+ assert_response :success
106
+ end
107
+ ```
108
+
109
+ after taking a look in `app/views/users/profile.erb`, looking at `/app/controllers/user_controller.rb`, examining the User model, and logging in to the website to browse this url, we find these setup requirements:
110
+ 1. The ability to login before running this test
111
+ 2. The link to this page is found on root page, which is what the first test covers. For consistency, we want to verify that the root page has this link.
112
+
113
+ Step two feels easier, so let's start with that, by turning the test from example one into a private method called 'visit_home', so we can call it as needed.
114
+
115
+ ```ruby
116
+ private
117
+
118
+ def visit_home
119
+ get_via_redirect '/'
120
+ assert_response :success
121
+ assert_template :index
122
+ end
123
+ ```
124
+
125
+ then change our old test to match, so we can see that visit_home works correctly. Tests testing tests, cats and dogs living together, mass hysteria! But hey, it lets us call 'visit_home', and have confidence that it works, before we embed it in another test.
126
+
127
+ rewritten test from example 1:
128
+
129
+ ```ruby
130
+ test "visit home url, ensure it redirects to index" do
131
+ visit_home
132
+ end
133
+ ```
134
+
135
+ Note that these tests are a stopgap. Some of them might turn out to be useful, but many of them will be too brittle for the long term. But they can provide a bridge that allows you to proceed with an upgrade, to preserve the current functionality of the site, and to exercise the site enough to generate deprecation warnings.
136
+
137
+ Now for step 1. We need a private method called 'login', as well as the relevant fixture data. The Users model shows that our fixture needs to contain a username at least 7 characters long, a password, a valid email, and a date that is in the future, for the 'expires_at' value.
138
+
139
+ The log reveals that logging in is executed as a `post` to `/user/login`, which passes this data:
140
+
141
+ `user: { login: <login> , password: <p> }`
142
+
143
+ At this point, it might be more useful to divert from writing these tests, to writing tests for the Users model, or at least create a to-do item somewhere, noting that the users model should have tests that ensure we come back to testing the things we discovered.
144
+
145
+
146
+ Additionally the database turns out to contain hashed passwords, so we dig into the User model, and find the command used to hash a password:
147
+ Digest::SHA1.hexdigest(password)
148
+
149
+
150
+ We now have enough information to create our fixture, which looks like this:
151
+ ```
152
+ good888:
153
+ login: good888
154
+ password: <%= Digest::SHA1.hexdigest("pw") %>
155
+ physician_name: good
156
+ email: good@email.com
157
+ expires_at: <%= (Date.today + 5.days).to_s(:db) %>
158
+ ```
159
+
160
+ So, now we can try to log in from our test. We should put login in its own method, but for now, let's just give this a shot as-is:
161
+
162
+ ```ruby
163
+ test "visit /user/profile/:id" do
164
+ visit_home
165
+ post '/user/login', user: { login: 'admin888' , password: 'pw' }
166
+ follow_redirect!
167
+ assert_response :success
168
+ assert_equal '/', path
169
+ get "/user/profile/#{users(:good888).id}"
170
+ assert_response :success
171
+ end
172
+ ```
173
+
174
+ We run it, it seems to work, so now we can add this line, to check for the profile link on the home page:
175
+
176
+ assert_select 'a[href=?]', "/user/profile/#{users(:good888).id}", {count: 1}
177
+
178
+ Then do a little refactoring, to break login into a reusable method, and finalize this test:
179
+
180
+ private login method:
181
+ ```ruby
182
+ def login(login, p)
183
+ post '/user/login', user: { login: login , password: p }
184
+ follow_redirect!
185
+ assert_response :success
186
+ assert_equal '/', path
187
+ end
188
+ ```
189
+
190
+ **The 'login' method could be useful in many places. If you find yourself needing it elsewhere, push it up into 'test/test_helper.rb', to make it available in your model/view/controller tests.**
191
+
192
+ cleaned up test:
193
+ ```ruby
194
+ test "login, make sure user profile link is available, and that we can visit it" do
195
+ visit_home
196
+ login('good888','pw')
197
+ user_id=users(:good888).id.to_s
198
+ assert_select 'a[href=?]', "/user/profile/#{user_id}", {count: 1}¬
199
+ get "/user/profile/#{user_id}"
200
+ assert_response :success
201
+ end
202
+ ```
203
+
204
+ ## Contributing
205
+
206
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tnordloh/your_legacy_tests. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
207
+
208
+
209
+ ## License
210
+
211
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
212
+
213
+ count defaults to 25, and controls the number of tests generated.
214
+
215
+ Results are generated on stdout, for maximum flexibility on where the tests are placed in the Rails application.
216
+
217
+ Here are some examples on how to modify the generated templates, for your application.
218
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/sumo_sum"
4
+
5
+ require 'getoptlong'
6
+
7
+ opts = GetoptLong.new(
8
+ ['--help','-h', GetoptLong::OPTIONAL_ARGUMENT],
9
+ ['--source_category','-s', GetoptLong::OPTIONAL_ARGUMENT],
10
+ ['--count','-c', GetoptLong::OPTIONAL_ARGUMENT],
11
+ )
12
+
13
+ source_category = "*"
14
+ count = 25
15
+
16
+ opts.each do |opt,arg|
17
+ case opt
18
+ when '--help'
19
+ puts <<-EOF
20
+ usage: #{ __FILE__ } [--help or -h] [-c or --count <count>]
21
+ [-s or --source_category <category>]
22
+
23
+ Specify number of tests returned, with most visited first
24
+ Defaults to 25:
25
+
26
+ #{ __FILE__ } -c, --count integer:
27
+
28
+ specify a source category in the sumo query.
29
+ defaults to "*":
30
+
31
+ #{ __FILE__ } -s, --source_category [source_category]:
32
+
33
+ show help:
34
+ #{ __FILE__ } -h, --help
35
+
36
+ EOF
37
+ exit 0
38
+ when '--source_category'
39
+
40
+ source_category=arg
41
+
42
+ when '--count'
43
+ raise "count not an integer" unless arg[/[0-9]+/].size == arg.size
44
+ count = arg.to_i
45
+ end
46
+ end
47
+
48
+ SumoSum.process(source_category, count)
49
+
@@ -0,0 +1,23 @@
1
+ TOP_CLASSES=' started |' +
2
+ ' parse regex "\s(?<protocol>.+)\s\"(?<pre>/.*)\" "|' +
3
+ 'where !(pre matches "*png*")|' +
4
+ 'where !(pre matches "*/assets*")|' +
5
+ 'where !(pre matches "*page=*" ) |' +
6
+ "split pre delim='/' extract 2 as class, 3 as method, 4 as id |" +
7
+ "split class delim='?' extract 1 as class |" +
8
+ "split method delim='?' extract 1 as method |" +
9
+ 'replace(method,"9","0") as method |' +
10
+ 'replace(method,"8","0") as method |' +
11
+ 'replace(method,"7","0") as method |' +
12
+ 'replace(method,"6","0") as method |' +
13
+ 'replace(method,"5","0") as method |' +
14
+ 'replace(method,"4","0") as method |' +
15
+ 'replace(method,"3","0") as method |' +
16
+ 'replace(method,"2","0") as method |' +
17
+ 'replace(method,"1","0") as method |' +
18
+ 'replace(method,"00000","0") as method |' +
19
+ 'replace(method,"0000","0") as method |' +
20
+ 'replace(method,"000","0") as method |' +
21
+ 'replace(method,"00","0") as method |' +
22
+ 'replace(method,"0",":id") as method |' +
23
+ 'count_frequent class,method,protocol'
@@ -0,0 +1,65 @@
1
+ require 'Sumo'
2
+ require 'Time'
3
+
4
+ require_relative './constants'
5
+ require_relative '../../lib/testing_your_legacy/testing_your_legacy'
6
+ require_relative '../../lib/testing_your_legacy/discover'
7
+
8
+ module SumoSum
9
+ class SumoSum
10
+
11
+ def initialize(source_category= "*",count=25)
12
+ @source_category = source_category
13
+ @count = count
14
+ end
15
+
16
+ attr_reader :source_category, :count
17
+
18
+ def sum_with_source
19
+ "_sourceCategory=" + source_category + " " + TOP_CLASSES
20
+ end
21
+
22
+ def top_visits
23
+ @top_visits ||= get_records
24
+ end
25
+
26
+ def get_records()
27
+ query = Sumo.search(query: sum_with_source,
28
+ from: "#{days_ago}",
29
+ to: "#{Time.now.utc.iso8601.chop}",
30
+ time_zone: 'UTC'
31
+ )
32
+
33
+ until query.status['state'] == "DONE GATHERING RESULTS" do
34
+ STDERR.puts "gathering results -- sleeping 2 seconds:records so far: #{query.status["recordCount"]}"
35
+ sleep 2
36
+ end
37
+ query.records
38
+ end
39
+
40
+ def each
41
+ top_visits.first(count).each do |record|
42
+ yield TestingYourLegacy::LogEntry.new(get_link(record),
43
+ record["protocol"],
44
+ record["_approxcount"])
45
+ end
46
+ end
47
+
48
+ def days_ago(days=90)
49
+ ninety_days_ago_in_seconds=60*60*24*days
50
+ (Time.now - ninety_days_ago_in_seconds).utc.iso8601.chop
51
+ end
52
+
53
+ def get_link(record)
54
+ "/" +
55
+ ["class","method"].map do |field|
56
+ record[field]
57
+ end
58
+ .reject {|field|
59
+ field==""
60
+ }
61
+ .join("/")
62
+ end
63
+ end
64
+ end
65
+
data/lib/sumo_sum.rb ADDED
@@ -0,0 +1,14 @@
1
+ require_relative "testing_your_legacy/discover"
2
+ require_relative "sumo_sum/sumo_sum"
3
+
4
+ module SumoSum
5
+ def self.process(source_category,count)
6
+ list = SumoSum.new(source_category,count)
7
+ discovers = TestingYourLegacy::Discover.new(list)
8
+
9
+ discovers.each do |r|
10
+ puts discovers.generate_method(r) + "\n"
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ require_relative './testing_your_legacy'
2
+ require 'erb'
3
+
4
+ module TestingYourLegacy
5
+ class Discover
6
+ def initialize(logs)
7
+ @logs=logs
8
+ end
9
+
10
+ def each
11
+ @logs.each do |record|
12
+ yield record
13
+ end
14
+ end
15
+
16
+ def generate_method(record)
17
+ @record = record
18
+ ERB.new(read_template('method_template.erb'))
19
+ .result(binding())
20
+ end
21
+
22
+ def generate_test(record)
23
+ @record = record
24
+ ERB.new(read_template('test_template.erb'))
25
+ .result(binding())
26
+ end
27
+
28
+ def read_template(template)
29
+ File.read(File.join(File.dirname(__FILE__), template))
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,6 @@
1
+ def <%= @record[:url].gsub("/","_") %>
2
+ #this url was visited <%= @record[:visits] %> times
3
+ <%= @record[:protocol].downcase %> <%= @record[:url] %>
4
+ assert_response :success
5
+ end
6
+
@@ -0,0 +1,6 @@
1
+ test "visit <%= @record[:url] %>" do
2
+ skip
3
+ #this url was visited <%= @record[:visits] %>
4
+ <%= @record[:protocol].downcase %> <%= @record[:url] %>
5
+ assert_response :success
6
+ end
@@ -0,0 +1,3 @@
1
+ module TestingYourLegacy
2
+ LogEntry=Struct.new(:url,:protocol,:visits)
3
+ end
@@ -0,0 +1,3 @@
1
+ module YourLegacyTests
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1 @@
1
+ require_relative 'testing_your_legacy/discover'
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'testing_your_legacy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "testing_your_legacy"
8
+ spec.version = YourLegacyTests::VERSION
9
+ spec.authors = ["Timothy Nordloh"]
10
+ spec.email = ["tnordloh@gmail.com"]
11
+
12
+ spec.summary = %q{Use Sumo Logic to generate tests for a Rails application, based on most frequently visited urls }
13
+ spec.homepage = "https://github.com/tnordloh/testing_your_legacy"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ #spec.metadata['allowed_push_host'] = "'http://mygemserver.com'"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "minitest"
32
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: testing_your_legacy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Timothy Nordloh
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - tnordloh@gmail.com
58
+ executables:
59
+ - tests_via_sumo
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - CODE_OF_CONDUCT.md
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/setup
70
+ - exe/tests_via_sumo
71
+ - lib/sumo_sum.rb
72
+ - lib/sumo_sum/constants.rb
73
+ - lib/sumo_sum/sumo_sum.rb
74
+ - lib/testing_your_legacy.rb
75
+ - lib/testing_your_legacy/discover.rb
76
+ - lib/testing_your_legacy/method_template.erb
77
+ - lib/testing_your_legacy/test_template.erb
78
+ - lib/testing_your_legacy/testing_your_legacy.rb
79
+ - lib/testing_your_legacy/version.rb
80
+ - testing_your_legacy.gemspec
81
+ homepage: https://github.com/tnordloh/testing_your_legacy
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.2.5
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Use Sumo Logic to generate tests for a Rails application, based on most frequently
105
+ visited urls
106
+ test_files: []