Skip to content

Commit

Permalink
Test transaction contents through extension
Browse files Browse the repository at this point in the history
Refactor the test suite to not test if transactions are created by
asserting method calls. Use the tooling to see if a transaction has been
created or not and assert what's set on the transaction using the
transaction matchers.

Part of #299
Closes #252
  • Loading branch information
tombruijn committed Jul 1, 2024
1 parent 90ced00 commit 7690559
Show file tree
Hide file tree
Showing 12 changed files with 319 additions and 352 deletions.
11 changes: 0 additions & 11 deletions spec/lib/appsignal/hooks/action_cable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ def self.to_s

set_current_transaction(transaction)

expect(Appsignal::Transaction).to receive(:create).with(
transaction_id,
Appsignal::Transaction::ACTION_CABLE,
kind_of(ActionDispatch::Request)
)
.and_return(transaction)
allow(Appsignal::Transaction).to receive(:current).and_return(transaction)

# Stub transmit call for subscribe/unsubscribe tests
allow(connection).to receive(:websocket)
.and_return(instance_double("ActionCable::Connection::WebSocket", :transmit => nil))
Expand Down Expand Up @@ -122,9 +114,6 @@ def self.to_s
kind_of(ActionDispatch::Request)
).and_return(action_transaction)
allow(Appsignal::Transaction).to receive(:current).and_return(action_transaction)
# Stub complete call, stops it from being cleared in the extension
# And allows us to call `#to_h` on it after it's been completed.
expect(action_transaction.ext).to receive(:complete)

instance.perform_action("message" => "foo", "action" => "speak")
expect(action_transaction).to have_id(transaction_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
end

it "does not instrument events whose name starts with a bang" do
expect(Appsignal::Transaction.current).not_to receive(:start_event)
expect(Appsignal::Transaction.current).not_to receive(:finish_event)

instrumenter.start("!sql.active_record", {})
instrumenter.finish("!sql.active_record", {})

Expand Down
49 changes: 7 additions & 42 deletions spec/lib/appsignal/hooks/net_http_spec.rb
Original file line number Diff line number Diff line change
@@ -1,51 +1,16 @@
describe Appsignal::Hooks::NetHttpHook do
before :context do
start_agent
end
before(:context) { start_agent }

context "with Net::HTTP instrumentation enabled" do
describe "#dependencies_present?" do
subject { described_class.new.dependencies_present? }
describe "#dependencies_present?" do
subject { described_class.new.dependencies_present? }

context "with Net::HTTP instrumentation enabled" do
it { is_expected.to be_truthy }
end

it "should instrument a http request" do
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
expect(Appsignal::Transaction.current).to receive(:start_event)
.at_least(:once)
expect(Appsignal::Transaction.current).to receive(:finish_event)
.at_least(:once)
.with("request.net_http", "GET http://www.google.com", nil, 0)

stub_request(:any, "http://www.google.com/")

Net::HTTP.get_response(URI.parse("http://www.google.com"))
end

it "should instrument a https request" do
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
expect(Appsignal::Transaction.current).to receive(:start_event)
.at_least(:once)
expect(Appsignal::Transaction.current).to receive(:finish_event)
.at_least(:once)
.with("request.net_http", "GET https://www.google.com", nil, 0)

stub_request(:any, "https://www.google.com/")

uri = URI.parse("https://www.google.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.get(uri.request_uri)
end
end

context "with Net::HTTP instrumentation disabled" do
before { Appsignal.config.config_hash[:instrument_net_http] = false }
after { Appsignal.config.config_hash[:instrument_net_http] = true }

describe "#dependencies_present?" do
subject { described_class.new.dependencies_present? }
context "with Net::HTTP instrumentation disabled" do
before { Appsignal.config.config_hash[:instrument_net_http] = false }
after { Appsignal.config.config_hash[:instrument_net_http] = true }

it { is_expected.to be_falsy }
end
Expand Down
33 changes: 33 additions & 0 deletions spec/lib/appsignal/integrations/net_http_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "appsignal/integrations/net_http"

describe Appsignal::Integrations::NetHttpIntegration do
let(:transaction) { http_request_transaction }
before(:context) { start_agent }
before { set_current_transaction transaction }
around { |example| keep_transactions { example.run } }

it "instruments a http request" do
stub_request(:any, "http://www.google.com/")

Net::HTTP.get_response(URI.parse("http://www.google.com"))

expect(transaction).to include_event(
"name" => "request.net_http",
"title" => "GET http://www.google.com"
)
end

it "instruments a https request" do
stub_request(:any, "https://www.google.com/")

uri = URI.parse("https://www.google.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.get(uri.request_uri)

expect(transaction).to include_event(
"name" => "request.net_http",
"title" => "GET https://www.google.com"
)
end
end
65 changes: 29 additions & 36 deletions spec/lib/appsignal/integrations/object_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "appsignal/integrations/object"

describe Object do
around { |example| keep_transactions { example.run } }

describe "#instrument_method" do
context "with instance method" do
let(:klass) do
Expand All @@ -24,10 +26,8 @@ def call_with_arguments
context "when active" do
let(:transaction) { http_request_transaction }
before do
Appsignal.config = project_fixture_config
expect(Appsignal::Transaction).to receive(:current)
.at_least(:once).and_return(transaction)
expect(Appsignal.active?).to be_truthy
start_agent
set_current_transaction(transaction)
end
after { Appsignal.config = nil }

Expand Down Expand Up @@ -80,10 +80,9 @@ def splat(*args, **kwargs)

context "with anonymous class" do
it "instruments the method and calls it" do
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"foo.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])

expect(transaction).to include_event("name" => "foo.AnonymousClass.other")
end
end

Expand All @@ -100,10 +99,9 @@ def foo
let(:klass) { NamedClass }

it "instruments the method and calls it" do
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"foo.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(instance.foo).to eq(1)

expect(transaction).to include_event("name" => "foo.NamedClass.other")
end
end

Expand All @@ -124,11 +122,11 @@ def bar
let(:klass) { MyModule::NestedModule::NamedClass }

it "instruments the method and calls it" do
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"bar.NamedClass.NestedModule.MyModule.other", nil, nil,
Appsignal::EventFormatter::DEFAULT
expect(instance.bar).to eq(2)

expect(transaction).to include_event(
"name" => "bar.NamedClass.NestedModule.MyModule.other"
)
end
end

Expand All @@ -143,10 +141,11 @@ def foo
end

it "instruments with custom name" do
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(instance.foo).to eq(1)

expect(transaction).to include_event(
"name" => "my_method.group"
)
end
end

Expand All @@ -160,7 +159,7 @@ def foo
end
end

it "should yield the block" do
it "yields the block" do
expect(instance.foo { 42 }).to eq(42)
end
end
Expand All @@ -171,7 +170,6 @@ def foo

it "does not instrument, but still calls the method" do
expect(Appsignal.active?).to be_falsy
expect(transaction).to_not receive(:start_event)
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
end
end
Expand All @@ -198,8 +196,7 @@ def call_with_arguments
let(:transaction) { http_request_transaction }
before do
Appsignal.config = project_fixture_config
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
.and_return(transaction)
set_current_transaction(transaction)
end
after { Appsignal.config = nil }

Expand Down Expand Up @@ -253,10 +250,10 @@ def self.splat(*args, **kwargs)
context "with anonymous class" do
it "instruments the method and calls it" do
expect(Appsignal.active?).to be_truthy
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"bar.class_method.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])

transaction._sample
expect(transaction).to include_event("name" => "bar.class_method.AnonymousClass.other")
end
end

Expand All @@ -274,10 +271,9 @@ def self.bar

it "instruments the method and calls it" do
expect(Appsignal.active?).to be_truthy
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"bar.class_method.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(klass.bar).to eq(2)

expect(transaction).to include_event("name" => "bar.class_method.NamedClass.other")
end

context "with nested named class" do
Expand All @@ -298,11 +294,10 @@ def self.bar

it "instruments the method and calls it" do
expect(Appsignal.active?).to be_truthy
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"bar.class_method.NamedClass.NestedModule.MyModule.other", nil, nil,
Appsignal::EventFormatter::DEFAULT
expect(klass.bar).to eq(2)
expect(transaction).to include_event(
"name" => "bar.class_method.NamedClass.NestedModule.MyModule.other"
)
end
end
end
Expand All @@ -319,10 +314,9 @@ def self.bar

it "instruments with custom name" do
expect(Appsignal.active?).to be_truthy
expect(transaction).to receive(:start_event)
expect(transaction).to receive(:finish_event).with \
"my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
expect(klass.bar).to eq(2)

expect(transaction).to include_event("name" => "my_method.group")
end
end

Expand All @@ -336,7 +330,7 @@ def self.bar
end
end

it "should yield the block" do
it "yields the block" do
expect(klass.bar { 42 }).to eq(42)
end
end
Expand All @@ -347,7 +341,6 @@ def self.bar

it "does not instrument, but still call the method" do
expect(Appsignal.active?).to be_falsy
expect(transaction).to_not receive(:start_event)
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
end
end
Expand Down
Loading

0 comments on commit 7690559

Please sign in to comment.