From 689c7caacb8ab3ba46be61c2f25e97e4559235c7 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Thu, 10 Oct 2024 20:01:43 +0300 Subject: [PATCH] Add Ecto test case and coverage tool (#68) Signed-off-by: Maciej Szlosarczyk maciej@mindvalley.com --- .github/workflows/gh-action-ci.yaml | 16 +++++++++++- .gitignore | 2 ++ mix.exs | 4 ++- mix.lock | 1 + .../lib/mv_opentelemetry_harness/page.ex | 6 ++++- test/mv_opentelemetry/ecto_test.exs | 26 +++++++++++++++++++ 6 files changed, 52 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gh-action-ci.yaml b/.github/workflows/gh-action-ci.yaml index c5ce856..dea5dbe 100644 --- a/.github/workflows/gh-action-ci.yaml +++ b/.github/workflows/gh-action-ci.yaml @@ -19,6 +19,9 @@ jobs: permissions: contents: read id-token: write + pull-requests: write + checks: write + runs-on: ubuntu-latest name: Test on OTP ${{ matrix.otp }} / Elixir ${{ matrix.elixir }} strategy: @@ -72,4 +75,15 @@ jobs: - name: Run mv-opentelemetry tests run: | - mix test + mix test --cover + + - name: Test coverage + uses: mindvalley/cobertura-action@master + with: + path: "mv_opentelemetry.covertool.xml" + minimum_coverage: 74 + report_name: "Test coverage: Elixir ${{matrix.elixir}} / OTP ${{matrix.otp}}" + show_missing: true + link_missing_lines: true + only_changed_files: true + link_missing_lines_source_dir: lib diff --git a/.gitignore b/.gitignore index 5b222ee..e12c0df 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ mv_opentelemetry-*.tar # Temporary files, for example, from tests. /tmp/ + +*.covertool.xml diff --git a/mix.exs b/mix.exs index 3823f40..b0546e0 100644 --- a/mix.exs +++ b/mix.exs @@ -11,6 +11,7 @@ defmodule MvOpentelemetry.MixProject do start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), + test_coverage: [tool: :covertool], dialyzer: [ plt_add_apps: [:mix, :ex_unit], ignore_warnings: ".known_dialyzer_warnings", @@ -59,7 +60,8 @@ defmodule MvOpentelemetry.MixProject do {:floki, ">= 0.30.0", only: :test}, {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}, - {:bypass, "~> 2.1", only: [:test]} + {:bypass, "~> 2.1", only: [:test]}, + {:covertool, "~> 2.0", only: [:test]} ] end diff --git a/mix.lock b/mix.lock index 6bff625..a7fe24a 100644 --- a/mix.lock +++ b/mix.lock @@ -8,6 +8,7 @@ "castore": {:hex, :castore, "0.1.20", "62a0126cbb7cb3e259257827b9190f88316eb7aa3fdac01fd6f2dfd64e7f46e9", [:mix], [], "hexpm", "a020b7650529c986c454a4035b6b13a328e288466986307bea3aadb4c95ac98a"}, "chatterbox": {:hex, :ts_chatterbox, "0.13.0", "6f059d97bcaa758b8ea6fffe2b3b81362bd06b639d3ea2bb088335511d691ebf", [:rebar3], [{:hpack, "~> 0.2.3", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "b93d19104d86af0b3f2566c4cba2a57d2e06d103728246ba1ac6c3c0ff010aa7"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, + "covertool": {:hex, :covertool, "2.0.7", "398be995c4cf1a2861174389b3577ca97beee43b60c8f1afcf510f1b07d32408", [:rebar3], [], "hexpm", "46158ed6e1a0df7c0a912e314c7b8e053bd74daa5fc6b790614922a155b5720c"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, diff --git a/mv_opentelemetry_harness/lib/mv_opentelemetry_harness/page.ex b/mv_opentelemetry_harness/lib/mv_opentelemetry_harness/page.ex index 9369831..33a2d31 100644 --- a/mv_opentelemetry_harness/lib/mv_opentelemetry_harness/page.ex +++ b/mv_opentelemetry_harness/lib/mv_opentelemetry_harness/page.ex @@ -1,6 +1,6 @@ defmodule MvOpentelemetryHarness.Page do use Ecto.Schema - import Ecto.Query, only: [from: 2] + import Ecto.Query, only: [from: 2, subquery: 1] alias Ecto.Changeset schema "pages" do @@ -20,4 +20,8 @@ defmodule MvOpentelemetryHarness.Page do def all do from p in __MODULE__, select: p end + + def custom_query do + from p in subquery(all()), select: %{title: p.title, id: p.id} + end end diff --git a/test/mv_opentelemetry/ecto_test.exs b/test/mv_opentelemetry/ecto_test.exs index 5d4344e..ffc5687 100644 --- a/test/mv_opentelemetry/ecto_test.exs +++ b/test/mv_opentelemetry/ecto_test.exs @@ -3,6 +3,32 @@ defmodule MvOpentelemetry.EctoTest do alias MvOpentelemetryHarness.Page alias MvOpentelemetryHarness.Repo + test "custom query has no" do + MvOpentelemetry.Ecto.register_tracer( + tracer_id: :test_ecto_tracer, + span_prefix: [:mv_opentelemetry_harness, :repo], + default_attributes: [{"service.component", "test.harness"}] + ) + + Page.custom_query() |> Repo.all() + + assert_receive {:span, span(name: "mv_opentelemetry_harness.repo") = span_record} + {:attributes, _, _, _, attributes} = span(span_record, :attributes) + keys = Enum.map(attributes, fn {k, _v} -> k end) + + assert {"db.type", :sql} in attributes + assert {"service.component", "test.harness"} in attributes + assert {"db.source", nil} in attributes + + assert "db.statement" in keys + assert "db.instance" in keys + assert "db.url" in keys + assert "db.total_time_microseconds" in keys + + :ok = + :telemetry.detach({[:mv_opentelemetry_harness, :repo], MvOpentelemetry.Ecto, :handle_event}) + end + test "sends otel events to pid" do MvOpentelemetry.Ecto.register_tracer( tracer_id: :test_ecto_tracer,