appmap 0.39.1 → 0.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/CONTRIBUTING.md +22 -0
  4. data/README.md +105 -50
  5. data/lib/appmap.rb +5 -0
  6. data/lib/appmap/class_map.rb +25 -8
  7. data/lib/appmap/command/record.rb +1 -1
  8. data/lib/appmap/config.rb +48 -28
  9. data/lib/appmap/event.rb +14 -4
  10. data/lib/appmap/hook.rb +7 -0
  11. data/lib/appmap/hook/method.rb +1 -1
  12. data/lib/appmap/middleware/remote_recording.rb +1 -1
  13. data/lib/appmap/minitest.rb +17 -14
  14. data/lib/appmap/rails/request_handler.rb +8 -3
  15. data/lib/appmap/railtie.rb +1 -5
  16. data/lib/appmap/rspec.rb +12 -78
  17. data/lib/appmap/version.rb +1 -1
  18. data/spec/abstract_controller_base_spec.rb +2 -2
  19. data/spec/config_spec.rb +1 -0
  20. data/spec/fixtures/hook/exclude.rb +15 -0
  21. data/spec/fixtures/hook/labels.rb +6 -0
  22. data/spec/fixtures/rails5_users_app/Gemfile +2 -3
  23. data/spec/fixtures/rails5_users_app/appmap.yml +4 -1
  24. data/spec/fixtures/rails5_users_app/config/application.rb +2 -0
  25. data/spec/fixtures/rails5_users_app/docker-compose.yml +3 -0
  26. data/spec/fixtures/rails5_users_app/spec/controllers/users_controller_api_spec.rb +3 -3
  27. data/spec/fixtures/rails5_users_app/spec/models/user_spec.rb +2 -12
  28. data/spec/fixtures/rails6_users_app/Gemfile +2 -3
  29. data/spec/fixtures/rails6_users_app/appmap.yml +4 -1
  30. data/spec/fixtures/rails6_users_app/config/application.rb +2 -0
  31. data/spec/fixtures/rails6_users_app/docker-compose.yml +3 -0
  32. data/spec/fixtures/rails6_users_app/spec/controllers/users_controller_api_spec.rb +3 -3
  33. data/spec/fixtures/rails6_users_app/spec/models/user_spec.rb +2 -12
  34. data/spec/hook_spec.rb +37 -1
  35. data/spec/record_sql_rails_pg_spec.rb +1 -1
  36. data/spec/spec_helper.rb +1 -0
  37. data/test/fixtures/gem_test/appmap.yml +1 -1
  38. data/test/fixtures/gem_test/test/parser_test.rb +12 -0
  39. data/test/fixtures/rspec_recorder/spec/decorated_hello_spec.rb +3 -3
  40. data/test/fixtures/rspec_recorder/spec/plain_hello_spec.rb +1 -1
  41. data/test/gem_test.rb +4 -4
  42. data/test/minitest_test.rb +1 -2
  43. data/test/rspec_test.rb +1 -7
  44. metadata +6 -4
  45. data/spec/rspec_feature_metadata_spec.rb +0 -31
  46. data/test/fixtures/gem_test/test/to_param_test.rb +0 -14
@@ -1,4 +1,7 @@
1
1
  name: rails5_users_app
2
2
  packages:
3
- - path: app
3
+ - path: app/models
4
+ labels: [ mvc.model ]
5
+ - path: app/controllers
6
+ labels: [ mvc.controller ]
4
7
  - gem: sequel
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -19,6 +19,9 @@ services:
19
19
  environment:
20
20
  RAILS_ENV:
21
21
  ORM_MODULE:
22
+ PGHOST: pg
23
+ PGPORT: '5432'
24
+ DATABASE_URL: postgres://postgres@pg
22
25
  APPMAP:
23
26
  volumes:
24
27
  - .:/src/app
@@ -1,8 +1,8 @@
1
1
  require 'rails_helper'
2
2
  require 'rack/test'
3
3
 
4
- RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller, appmap: true do
5
- describe 'POST /api/users', feature: 'Create a user' do
4
+ RSpec.describe Api::UsersController, type: :controller do
5
+ describe 'POST /api/users' do
6
6
  describe 'with required parameters' do
7
7
  it 'creates a user' do
8
8
  post :create, params: { login: 'alice', password: 'foobar' }
@@ -16,7 +16,7 @@ RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller,
16
16
  end
17
17
  end
18
18
  end
19
- describe 'GET /api/users', feature: 'List users' do
19
+ describe 'GET /api/users' do
20
20
  before do
21
21
  post :create, params: { login: 'alice' }
22
22
  end
@@ -1,6 +1,6 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe User, feature_group: 'User', appmap: true do
3
+ describe User do
4
4
  # TODO: appmap/rspec doesn't handle shared_examples_for 100% correctly yet.
5
5
  # In my tests, only one of these two tests will be emitted as an appmap.
6
6
  shared_examples_for 'creates the user' do |username|
@@ -11,17 +11,7 @@ describe User, feature_group: 'User', appmap: true do
11
11
  end
12
12
  end
13
13
 
14
- describe 'creation', feature: 'Create a user' do
15
- context 'using shared_examples_for' do
16
- # AppMap.
17
- # context "with username 'alice'" do
18
- # it_should_behave_like 'creates the user', 'alice'
19
- # end
20
- # context "with username 'bob'" do
21
- # it_should_behave_like 'creates the user', 'bob'
22
- # end
23
- end
24
-
14
+ describe 'creation' do
25
15
  # So, instead of shared_examples_for, let's go with a simple method
26
16
  # containing the assertions. The method can be called from within an example.
27
17
  def save_and_verify
@@ -34,11 +34,10 @@ appmap_options = \
34
34
  { path: appmap_path }
35
35
  else
36
36
  {}
37
- end.merge(require: %w[appmap appmap/railtie])
38
-
39
- gem 'appmap', appmap_options
37
+ end.merge(require: %w[appmap])
40
38
 
41
39
  group :development, :test do
40
+ gem 'appmap', appmap_options
42
41
  gem 'cucumber-rails', require: false
43
42
  gem 'rspec-rails'
44
43
  # Required for Sequel, since without ActiveRecord, the Rails transactional fixture support
@@ -1,5 +1,8 @@
1
1
  name: rails6_users_app
2
2
  packages:
3
- - path: app
3
+ - path: app/models
4
+ labels: [ mvc.model ]
5
+ - path: app/controllers
6
+ labels: [ mvc.controller ]
4
7
  - gem: sequel
5
8
 
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -19,6 +19,9 @@ services:
19
19
  environment:
20
20
  RAILS_ENV:
21
21
  ORM_MODULE:
22
+ PGHOST: pg
23
+ PGPORT: '5432'
24
+ DATABASE_URL: postgres://postgres@pg
22
25
  APPMAP:
23
26
  volumes:
24
27
  - .:/src/app
@@ -1,8 +1,8 @@
1
1
  require 'rails_helper'
2
2
  require 'rack/test'
3
3
 
4
- RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller, appmap: true do
5
- describe 'POST /api/users', feature: 'Create a user' do
4
+ RSpec.describe Api::UsersController, type: :controller do
5
+ describe 'POST /api/users' do
6
6
  describe 'with required parameters' do
7
7
  it 'creates a user' do
8
8
  post :create, params: { login: 'alice', password: 'foobar' }
@@ -16,7 +16,7 @@ RSpec.describe Api::UsersController, feature_group: 'Users', type: :controller,
16
16
  end
17
17
  end
18
18
  end
19
- describe 'GET /api/users', feature: 'List users' do
19
+ describe 'GET /api/users' do
20
20
  before do
21
21
  post :create, params: { login: 'alice' }
22
22
  end
@@ -1,6 +1,6 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe User, feature_group: 'User', appmap: true do
3
+ describe User do
4
4
  # TODO: appmap/rspec doesn't handle shared_examples_for 100% correctly yet.
5
5
  # In my tests, only one of these two tests will be emitted as an appmap.
6
6
  shared_examples_for 'creates the user' do |username|
@@ -11,17 +11,7 @@ describe User, feature_group: 'User', appmap: true do
11
11
  end
12
12
  end
13
13
 
14
- describe 'creation', feature: 'Create a user' do
15
- context 'using shared_examples_for' do
16
- # AppMap.
17
- # context "with username 'alice'" do
18
- # it_should_behave_like 'creates the user', 'alice'
19
- # end
20
- # context "with username 'bob'" do
21
- # it_should_behave_like 'creates the user', 'bob'
22
- # end
23
- end
24
-
14
+ describe 'creation' do
25
15
  # So, instead of shared_examples_for, let's go with a simple method
26
16
  # containing the assertions. The method can be called from within an example.
27
17
  def save_and_verify
data/spec/hook_spec.rb CHANGED
@@ -61,6 +61,42 @@ describe 'AppMap class Hooking', docker: false do
61
61
  AppMap.configuration = nil
62
62
  end
63
63
 
64
+ it 'excludes named classes and methods' do
65
+ load 'spec/fixtures/hook/exclude.rb'
66
+ package = AppMap::Config::Package.build_from_path('spec/fixtures/hook/exclude.rb')
67
+ config = AppMap::Config.new('hook_spec', [ package ], %w[ExcludeTest])
68
+ AppMap.configuration = config
69
+
70
+ expect(config.never_hook?(ExcludeTest.new.method(:instance_method))).to be_truthy
71
+ expect(config.never_hook?(ExcludeTest.method(:cls_method))).to be_truthy
72
+ end
73
+
74
+ it 'parses labels from comments' do
75
+ _, tracer = invoke_test_file 'spec/fixtures/hook/labels.rb' do
76
+ ClassWithLabel.new.fn_with_label
77
+ end
78
+ class_map = AppMap.class_map(tracer.event_methods).to_yaml
79
+ expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
80
+ ---
81
+ - :name: spec/fixtures/hook/labels.rb
82
+ :type: package
83
+ :children:
84
+ - :name: ClassWithLabel
85
+ :type: class
86
+ :children:
87
+ - :name: fn_with_label
88
+ :type: function
89
+ :location: spec/fixtures/hook/labels.rb:4
90
+ :static: false
91
+ :labels:
92
+ - has-fn-label
93
+ :comment: "# @label has-fn-label\\n"
94
+ :source: |2
95
+ def fn_with_label
96
+ end
97
+ YAML
98
+ end
99
+
64
100
  it 'hooks an instance method that takes no arguments' do
65
101
  events_yaml = <<~YAML
66
102
  ---
@@ -801,7 +837,7 @@ describe 'AppMap class Hooking', docker: false do
801
837
  entry = cm[1][:children][0][:children][0][:children][0]
802
838
  # Sanity check, make sure we got the right one
803
839
  expect(entry[:name]).to eq('secure_compare')
804
- expect(entry[:labels]).to eq(%w[security crypto])
840
+ expect(entry[:labels]).to eq(%w[provider.secure_compare])
805
841
  end
806
842
  end
807
843
 
@@ -5,7 +5,7 @@ describe 'SQL events' do
5
5
  around(:each) do |example|
6
6
  FileUtils.rm_rf tmpdir
7
7
  FileUtils.mkdir_p tmpdir
8
- cmd = "docker-compose run --rm -e ORM_MODULE=#{orm_module} -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:#{test_line_number}"
8
+ cmd = "docker-compose run --rm -e ORM_MODULE=#{orm_module} -e RAILS_ENV=test -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:#{test_line_number}"
9
9
  run_cmd cmd, chdir: fixture_dir
10
10
 
11
11
  example.run
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ require 'net/http'
3
3
  require 'json'
4
4
  require 'yaml'
5
5
  require 'English'
6
+ require 'byebug'
6
7
  require 'webdrivers/chromedriver'
7
8
 
8
9
  # Disable default initialization of AppMap
@@ -1,3 +1,3 @@
1
1
  name: gem_test
2
2
  packages:
3
- - gem: activesupport
3
+ - gem: parser
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'appmap/minitest'
5
+ require 'minitest/autorun'
6
+ require 'parser/current'
7
+
8
+ class ParserTest < ::Minitest::Test
9
+ def test_parser
10
+ Parser::CurrentRuby.parse(File.read(__FILE__))
11
+ end
12
+ end
@@ -2,7 +2,7 @@ require 'rspec'
2
2
  require 'appmap/rspec'
3
3
  require 'hello'
4
4
 
5
- describe Hello, feature_group: 'Saying hello' do
5
+ describe Hello do
6
6
  before do
7
7
  # Trick appmap-ruby into thinking we're a Rails app.
8
8
  stub_const('Rails', double('rails', version: 'fake.0'))
@@ -11,11 +11,11 @@ describe Hello, feature_group: 'Saying hello' do
11
11
  # The order of these examples is important. The tests check the
12
12
  # appmap for 'says hello', and we want another example to get run
13
13
  # before it.
14
- it 'does not say goodbye', feature: 'Speak hello', appmap: true do
14
+ it 'does not say goodbye' do
15
15
  expect(Hello.new.say_hello).not_to eq('Goodbye!')
16
16
  end
17
17
 
18
- it 'says hello', feature: 'Speak hello', appmap: true do
18
+ it 'says hello' do
19
19
  expect(Hello.new.say_hello).to eq('Hello!')
20
20
  end
21
21
  end
@@ -2,7 +2,7 @@ require 'rspec'
2
2
  require 'appmap/rspec'
3
3
  require 'hello'
4
4
 
5
- describe Hello, appmap: true do
5
+ describe Hello do
6
6
  it 'says hello' do
7
7
  expect(Hello.new.say_hello).to eq('Hello!')
8
8
  end
data/test/gem_test.rb CHANGED
@@ -19,14 +19,14 @@ class MinitestTest < Minitest::Test
19
19
  end
20
20
 
21
21
  def test_record_gem
22
- perform_gem_test 'to_param' do
23
- appmap_file = 'tmp/appmap/minitest/To_param_to_param.appmap.json'
22
+ perform_gem_test 'parser' do
23
+ appmap_file = 'tmp/appmap/minitest/Parser_parser.appmap.json'
24
24
  appmap = JSON.parse(File.read(appmap_file))
25
25
  events = appmap['events']
26
26
  assert_equal 2, events.size
27
27
  assert_equal 'call', events.first['event']
28
- assert_equal 'to_param', events.first['method_id']
29
- assert_equal "#{Gem.loaded_specs['activesupport'].gem_dir}/lib/active_support/core_ext/object/to_query.rb", events.first['path']
28
+ assert_equal 'default_parser', events.first['method_id']
29
+ assert_equal "#{Gem.loaded_specs['parser'].gem_dir}/lib/parser/base.rb", events.first['path']
30
30
  assert_equal 'return', events.second['event']
31
31
  assert_equal 1, events.second['parent_id']
32
32
  end
@@ -30,9 +30,8 @@ class MinitestTest < Minitest::Test
30
30
  assert_equal 'minitest_recorder', metadata['app']
31
31
  assert_equal 'minitest', metadata['recorder']['name']
32
32
  assert_equal 'ruby', metadata['language']['name']
33
- assert_equal 'Hello', metadata['feature_group']
34
- assert_equal 'hello', metadata['feature']
35
33
  assert_equal 'Hello hello', metadata['name']
34
+ assert_equal 'test/hello_test.rb:9', metadata['source_location']
36
35
  end
37
36
  end
38
37
  end
data/test/rspec_test.rb CHANGED
@@ -28,8 +28,6 @@ class RSpecTest < Minitest::Test
28
28
  assert_includes appmap.keys, 'metadata'
29
29
  metadata = appmap['metadata']
30
30
  assert_equal 'Inventory', metadata['name']
31
- assert_includes metadata.keys, 'labels'
32
- assert_equal metadata['labels'], %w[inventory]
33
31
  end
34
32
  end
35
33
 
@@ -42,9 +40,8 @@ class RSpecTest < Minitest::Test
42
40
  assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
43
41
  assert_includes appmap.keys, 'metadata'
44
42
  metadata = appmap['metadata']
45
- assert_equal 'Saying hello', metadata['feature_group']
46
- assert_equal 'Speak hello', metadata['feature']
47
43
  assert_equal 'Hello says hello', metadata['name']
44
+ assert_equal 'spec/decorated_hello_spec.rb', metadata['source_location']
48
45
  assert_includes metadata.keys, 'client'
49
46
  assert_equal({ name: 'appmap', url: AppMap::URL, version: AppMap::VERSION }.stringify_keys, metadata['client'])
50
47
  assert_includes metadata.keys, 'recorder'
@@ -63,8 +60,6 @@ class RSpecTest < Minitest::Test
63
60
  appmap = JSON.parse(File.read(appmap_file))
64
61
  assert_includes appmap.keys, 'metadata'
65
62
  metadata = appmap['metadata']
66
- assert_equal 'Hello', metadata['feature_group']
67
- assert_equal 'Hello', metadata['feature']
68
63
  assert_equal 'Hello says hello', metadata['name']
69
64
  end
70
65
  end
@@ -76,7 +71,6 @@ class RSpecTest < Minitest::Test
76
71
  appmap = JSON.parse(File.read(appmap_file))
77
72
  assert_includes appmap.keys, 'metadata'
78
73
  metadata = appmap['metadata']
79
- assert_equal %w[hello speak], metadata['labels'].sort
80
74
  end
81
75
  end
82
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.1
4
+ version: 0.42.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-22 00:00:00.000000000 Z
11
+ date: 2021-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -319,6 +319,7 @@ files:
319
319
  - ".rubocop.yml"
320
320
  - ".travis.yml"
321
321
  - CHANGELOG.md
322
+ - CONTRIBUTING.md
322
323
  - Dockerfile.appmap
323
324
  - Gemfile
324
325
  - LICENSE.txt
@@ -385,7 +386,9 @@ files:
385
386
  - spec/fixtures/hook/compare.rb
386
387
  - spec/fixtures/hook/constructor.rb
387
388
  - spec/fixtures/hook/exception_method.rb
389
+ - spec/fixtures/hook/exclude.rb
388
390
  - spec/fixtures/hook/instance_method.rb
391
+ - spec/fixtures/hook/labels.rb
389
392
  - spec/fixtures/hook/singleton_method.rb
390
393
  - spec/fixtures/rack_users_app/.dockerignore
391
394
  - spec/fixtures/rack_users_app/.gitignore
@@ -545,7 +548,6 @@ files:
545
548
  - spec/railtie_spec.rb
546
549
  - spec/record_sql_rails_pg_spec.rb
547
550
  - spec/remote_recording_spec.rb
548
- - spec/rspec_feature_metadata_spec.rb
549
551
  - spec/spec_helper.rb
550
552
  - spec/util_spec.rb
551
553
  - test/cli_test.rb
@@ -570,7 +572,7 @@ files:
570
572
  - test/fixtures/cucumber_recorder/lib/hello.rb
571
573
  - test/fixtures/gem_test/Gemfile
572
574
  - test/fixtures/gem_test/appmap.yml
573
- - test/fixtures/gem_test/test/to_param_test.rb
575
+ - test/fixtures/gem_test/test/parser_test.rb
574
576
  - test/fixtures/minitest_recorder/Gemfile
575
577
  - test/fixtures/minitest_recorder/appmap.yml
576
578
  - test/fixtures/minitest_recorder/lib/hello.rb
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails_spec_helper'
4
-
5
- describe 'RSpec feature and feature group metadata' do
6
- include_examples 'Rails app pg database', 'spec/fixtures/rails5_users_app' do
7
- around(:each) do |example|
8
- FileUtils.rm_rf tmpdir
9
- FileUtils.mkdir_p tmpdir
10
- cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path(tmpdir).shellescape}:/app/tmp app ./bin/rspec spec/models/user_spec.rb"
11
- run_cmd cmd, chdir: fixture_dir
12
-
13
- example.run
14
- end
15
-
16
- let(:tmpdir) { 'tmp/spec/RSpec feature and feature group metadata' }
17
- let(:appmap_json) { File.join(tmpdir, %(appmap/rspec/User_creation_creates_charles.appmap.json)) }
18
-
19
- describe do
20
- it 'are recorded in the appmap' do
21
- expect(File).to exist(appmap_json)
22
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
23
-
24
- expect(appmap).to include(<<-METADATA.strip)
25
- feature: Create a user
26
- feature_group: User
27
- METADATA
28
- end
29
- end
30
- end
31
- end