Skip to content

Commit

Permalink
feat: factory_default profiler support + chore
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Aug 2, 2024
1 parent 56e18b3 commit 4f1d2c8
Show file tree
Hide file tree
Showing 41 changed files with 306 additions and 39 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release gems
on:
workflow_dispatch:
push:
tags:
- v*

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch current tag as annotated. See https://github.com/actions/checkout/issues/290
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2
- name: Configure RubyGems Credentials
uses: rubygems/configure-rubygems-credentials@main
- name: Publish to RubyGems
run: |
gem install gem-release
gem release
13 changes: 2 additions & 11 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,13 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: ["2.7", "3.0", "3.1"]
coverage: ["false"]
include:
- ruby: "3.2"
coverage: "true"
ruby: ["3.0", "3.1", "3.2", "3.3"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run RSpec
run: |
bundle exec rspec
- name: Coveralls
if: false # ${{ matrix.coverage == 'true' }}
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
9 changes: 5 additions & 4 deletions .github/workflows/rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ on:
jobs:
rubocop:
runs-on: ubuntu-latest
env:
BUNDLE_GEMFILE: gemfiles/rubocop.gemfile
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0
ruby-version: 3.2
bundler-cache: true
- name: Lint Ruby code with RuboCop
run: |
gem install bundler
bundle install --gemfile gemfiles/rubocop.gemfile --jobs 4 --retry 3
bundle exec --gemfile gemfiles/rubocop.gemfile rubocop
bundle exec rubocop
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## master

- Add FactoryDefault profiler support. ([@palkan][])

## 0.1.0 (2023-11-21)

- Initial public release. ([@palkan][])
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ source "https://rubygems.org"

gem "debug", platform: :mri
gem "factory_bot"
gem "test-prof"

gemspec

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Currently, Autopilot supports the following Test Prof profilers:
- [TagProf](https://test-prof.evilmartians.io/profilers/tag_prof) (as `:tag_prof`)
- [StackProf](https://test-prof.evilmartians.io/profilers/stack_prof) (as `:stack_prof`)
- [FactoryProf](https://test-prof.evilmartians.io/profilers/factory_prof) (as `:factory_prof`)
- [FactoryDefault profiler](https://test-prof.evilmartians.io/recipes/factory_default) (as `:factory_default_prof`)

## Installation

Expand Down
1 change: 1 addition & 0 deletions lib/test_prof/autopilot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
require "test_prof/autopilot/patches/event_prof_patch"
require "test_prof/autopilot/patches/tag_prof_patch"
require "test_prof/autopilot/patches/factory_prof_patch"
require "test_prof/autopilot/patches/factory_default_patch"
require "test_prof/autopilot/patches/stack_prof_patch"
end
4 changes: 4 additions & 0 deletions lib/test_prof/autopilot/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
require "test_prof/autopilot/stack_prof/writer"
require "test_prof/autopilot/stack_prof/profiling_executor"

require "test_prof/autopilot/factory_default/printer"
require "test_prof/autopilot/factory_default/writer"
require "test_prof/autopilot/factory_default/profiling_executor"

module TestProf
module Autopilot
# Module contains all available DSL instructions
Expand Down
25 changes: 25 additions & 0 deletions lib/test_prof/autopilot/factory_default/printer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module TestProf
module Autopilot
module FactoryDefault
# Module is used for printing :factory_prof report
module Printer
Registry.register(:factory_default_prof_printer, self)

class PrinterError < StandardError; end

def print_report(report)
result = report.result

require "test_prof/factory_default"
profiler = TestProf::FactoryDefault::Profiler.new
profiler.data.merge!(result)
profiler.print_report
end

module_function :print_report
end
end
end
end
28 changes: 28 additions & 0 deletions lib/test_prof/autopilot/factory_default/profiling_executor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require "test_prof/autopilot/profiling_executor/base"

module TestProf
module Autopilot
module FactoryDefault
# Provides :factory_default_prof specific validations, env and command building.
class ProfilingExecutor < ProfilingExecutor::Base
Registry.register(:factory_default_prof_executor, self)

def initialize(options)
super
@profiler = :factory_default_prof
end

private

def build_env
super.tap do |env|
env["FACTORY_DEFAULT_ENABLED"] = "true"
env["FACTORY_DEFAULT_PROF"] = "1"
end
end
end
end
end
end
48 changes: 48 additions & 0 deletions lib/test_prof/autopilot/factory_default/report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require "json"
require "test_prof/autopilot/report_builder"

module TestProf
module Autopilot
module FactoryDefault
class Report
Registry.register(:factory_default_prof_report, self)

extend ReportBuilder

ARTIFACT_FILE = "factory_default_prof_report.json"

attr_reader :type, :raw_report

def initialize(raw_report)
@type = :factory_default_prof
@raw_report = raw_report
end

def result
@result ||= raw_report.tap { |r| r.transform_values! { |v| v.transform_keys!(&:to_sym) } }
end

def factories
result.dup
end

def merge(other)
report = result.dup

other.result.each do |name, stats|
if result.key?(name)
report[name][:count] += stats[:count]
report[name][:time] += stats[:time]
else
report[name] = stats
end
end

Report.new(report)
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/test_prof/autopilot/factory_default/writer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module TestProf
module Autopilot
module FactoryDefault
# Class is used for writing :factory_prof report in different formats
class Writer < ReportWriter
Registry.register(:factory_default_prof_writer, self)

ARTIFACT_FILE = "factory_default_prof_report"

def generate_json
report.result.to_json
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/test_prof/autopilot/factory_prof/printer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def print_report(report)
result = report.result

# TODO: Move total_time to the report
TestProf::FactoryProf::Printers::Simple.dump(result, start_time: TestProf.now)
TestProf::FactoryProf::Printers::Simple.dump(result, start_time: TestProf.now, threshold: 0)
end

module_function :print_report
Expand Down
43 changes: 43 additions & 0 deletions lib/test_prof/autopilot/patches/factory_default_patch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

module TestProf
module Autopilot
module Patches
module FactoryDefaultPatch
ARTIFACT_FILE = "factory_default_prof_report.json"

module ProfilerExt
def print_report
# TODO: extract it into a method in TestProf
data = self.data.each_with_object({}) do |(name, stats), acc|
name = name.gsub(/\$id\$.+\$di\$/, "<id>")
if acc.key?(name)
acc[name][:count] += stats[:count]
acc[name][:time] += stats[:time]
else
acc[name] = stats
end
end

dir_path = FileUtils.mkdir_p(Autopilot.config.tmp_dir)[0]
file_path = File.join(dir_path, ARTIFACT_FILE)

File.write(file_path, data.to_json)
end
end

def patch
::TestProf::FactoryDefault::Profiler.prepend(ProfilerExt)
end

module_function :patch
end
end
end
end

if ENV["FACTORY_DEFAULT_ENABLED"] == "true"
require "test_prof/factory_default"
require "test_prof/recipes/rspec/factory_default"
TestProf::Autopilot::Patches::FactoryDefaultPatch.patch
end
1 change: 1 addition & 0 deletions lib/test_prof/autopilot/profiling_executor/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require "test_prof/autopilot/event_prof/report"
require "test_prof/autopilot/tag_prof/report"
require "test_prof/autopilot/factory_prof/report"
require "test_prof/autopilot/factory_default/report"
require "test_prof/autopilot/stack_prof/report"

module TestProf
Expand Down
6 changes: 4 additions & 2 deletions spec/fixtures/factory_prof_flamegraph_report.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
"total_count": 5,
"top_level_count": 5,
"total_time": 0.0022159996442496777,
"top_level_time": 0.0022159996442496777
"top_level_time": 0.0022159996442496777,
"variations": {}
},
"account": {
"name": "account",
"total_count": 4,
"top_level_count": 2,
"total_time": 0.02294999547302723,
"top_level_time": 0.02294999547302723
"top_level_time": 0.02294999547302723,
"variations": {}
}
}
}
9 changes: 6 additions & 3 deletions spec/fixtures/factory_prof_flamegraph_report_2.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,24 @@
"total_count": 3,
"top_level_count": 0,
"total_time": 0.0022159996442496777,
"top_level_time": 0.0022159996442496777
"top_level_time": 0.0022159996442496777,
"variations": {}
},
"post": {
"name": "post",
"total_count": 6,
"top_level_count": 6,
"total_time": 0.0022159996442496777,
"top_level_time": 0.0022159996442496777
"top_level_time": 0.0022159996442496777,
"variations": {}
},
"account": {
"name": "account",
"total_count": 1,
"top_level_count": 0,
"total_time": 0.02294999547302723,
"top_level_time": 0.02294999547302723
"top_level_time": 0.02294999547302723,
"variations": {}
}
}
}
6 changes: 4 additions & 2 deletions spec/fixtures/factory_prof_report.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
"total_count": 5,
"top_level_count": 5,
"total_time": 0.002294999547302723,
"top_level_time": 0.002294999547302723
"top_level_time": 0.002294999547302723,
"variations": {}
},
"account": {
"name": "account",
"total_count": 4,
"top_level_count": 2,
"total_time": 0.02294999547302723,
"top_level_time": 0.02294999547302723
"top_level_time": 0.02294999547302723,
"variations": {}
}
}
}
9 changes: 9 additions & 0 deletions spec/fixtures/plans/factory_default_prof_plan.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

run :factory_default_prof

info report

report.factories.select { |_, v| v[:count] > 1 }.each do |name, stats|
puts "#{name} - #{stats[:count]} times, #{stats[:time]}s"
end
4 changes: 2 additions & 2 deletions spec/fixtures/tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class User
end

class Job
attr_accessor :title
attr_accessor :title, :user
end

FactoryBot.define do
Expand Down Expand Up @@ -41,7 +41,7 @@ class Job
end

describe "Another something", type: :any do
before { FactoryBot.create(:user) }
before { FactoryBot.create(:job) }

it "do something" do
expect(true).to eq true
Expand Down
Loading

0 comments on commit 4f1d2c8

Please sign in to comment.