Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor OutdatedGem; install FactoryBot for improved test coverage #5

Merged
merged 7 commits into from
Jul 14, 2024

Conversation

mattbrictson
Copy link
Owner

@mattbrictson mattbrictson commented Jul 14, 2024

The core model class of this project is OutdatedGem. Currently, an instance of this class represents a complex object graph that is tightly coupled with Bundler classes like Bundler::LazySpecification. Because of this complexity and broad scope, writing test coverage for different scenarios involving OutdatedGem is prohibitively difficult without a significant amount of mocking or fixture setup.

This PR addresses this problem by refactoring OutdatedGem to be a shallow, struct-like data class that no longer has external Bundler dependencies.

With that refactor in place, I was able to install FactoryBot and use it to easily write some new unit tests for CLI::Row.

@mattbrictson mattbrictson added the 🏠 Housekeeping Non-user facing cleanup and maintenance label Jul 14, 2024
@@ -3,14 +3,17 @@
source "https://rubygems.org"
gemspec

gem "factory_bot", "~> 6.3.0"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗒️ I had to pin at 6.3 because newer versions of FactoryBot do not support Ruby 2.7, which is still part of our CI.

gem "minitest", "~> 5.11"
gem "minitest-snapshots", "~> 1.1"
gem "mocha", "~> 2.4"
gem "observer"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗒️ FactoryBot 6.3 has an undeclared dependency on observer, which won't be part of Ruby 3.4. I had to make it an explicit dependency so that CI would pass on Ruby head.

@@ -28,7 +28,7 @@ def render_gem(name)

def render
lines = [render_header]
rows.each_key { |name| lines << render_gem(name) }
rows.keys.sort.each { |name| lines << render_gem(name) }
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗒️ I moved sorting behavior into CLI::Table, out of the core Report class. This makes the report implementation simpler, and sorting is naturally more of a UI (CLI in our case) concern.

attr_reader :current_lockfile_entry, :updated_lockfile_entry, :gemfile_groups
attr_writer :vulnerable
attr_accessor :name,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗒️ This refactor removes dependencies on lock file entries (which are deep data structures that in turn depend on internal Bundler classes) in favor of a flat set of simple PORO attributes.

class BundleUpdateInteractive::CLI
class RowTest < Minitest::Test
def test_formatted_gem_name_for_vulnerable_gem_is_red_on_white
outdated_gem = build(:outdated_gem, name: "rails", vulnerable: true)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗒️ These tests were super easy to write, because I can now use FactoryBot's build to construct the exact scenarios I needed.

@mattbrictson mattbrictson marked this pull request as ready for review July 14, 2024 23:48
@mattbrictson mattbrictson merged commit 29f6c80 into main Jul 14, 2024
8 checks passed
@mattbrictson mattbrictson deleted the refactor-and-factory-bot branch July 14, 2024 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏠 Housekeeping Non-user facing cleanup and maintenance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant