https://github.com/mastert/flaky_test_tracker
Automatic flaky test tracking system.
https://github.com/mastert/flaky_test_tracker
flaky flaky-tests ruby test tracking
Last synced: 9 months ago
JSON representation
Automatic flaky test tracking system.
- Host: GitHub
- URL: https://github.com/mastert/flaky_test_tracker
- Owner: masterT
- License: mit
- Created: 2021-08-01T11:23:42.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2022-03-28T19:21:17.000Z (about 4 years ago)
- Last Synced: 2023-08-05T16:03:32.975Z (almost 3 years ago)
- Topics: flaky, flaky-tests, ruby, test, tracking
- Language: Ruby
- Homepage:
- Size: 204 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# FlakyTestTracker
> **:warning: Work in progress**
[](https://github.com/masterT/flaky_test_tracker/actions/workflows/build.yml)
FlakyTestTracker is an automatic flaky test tracking system. It is testing framework agnostic and very customizable.
Features:
- automatically [track](#track) failing tests
- automatically [resolve](#resolve) tracked failing tests
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'flaky_test_tracker'
```
And then execute:
```
$ bundle install
```
Or install it yourself as:
```
$ gem install flaky_test_tracker
```
## Documentation
The documentation is available online on [rubydoc.info](https://rubydoc.info/github/masterT/flaky_test_tracker).
## Usage
### Track
You can automatically track failing tests on the configured [storage](#storage) for any testing framework, as long as it can provide a unique _reference_ to identify the test.
Add failing test attributes to the internal queue:
```ruby
FlakyTestTracker.tracker.add(
reference: "./spec/foo_spec.rb[1:2]",
description: "returns true when foo",
exception: %{
expected: true
got: false
(compared using ==)
Diff:
@@ -1 +1 @@
-true
+false
},
file_path: "./spec/foo_spec.rb",
line_number: 8
)
```
Persists the test on the configured storage.
When test attributes has a `reference` matching a test persisted in the configured storage, the test's `number_occurrences` attribute will be incremented and the test will be updated with the test attributes. Otherwise, a test will be created with the test attributes and `number_occurrences` equals to `1`.
```ruby
FlakyTestTracker.tracker.track
```
Reset the test attributes internal queue:
```ruby
FlakyTestTracker.tracker.clear
```
#### Examples
Example with [RSpec](https://rubygems.org/gems/rspec) testing framework.
```ruby
RSpec.configure do |config|
config.before(:suite) do
FlakyTestTracker.tracker.clear
end
config.after do |example|
if example.exception
FlakyTestTracker.tracker.add(
reference: example.id,
description: example.full_description,
exception: example.exception.gsub(/\x1b\[[0-9;]*[a-zA-Z]/, ""), # Remove ANSI formatting.
file_path: example.metadata[:file_path],
line_number: example.metadata[:line_number]
)
end
end
config.after(:suite) do
FlakyTestTracker.tracker.track
rescue StandardError
# ...
end
end
```
### Resolve
You can automatically resolve previously tracked failing tests on the configured [storage](#storage).
The `resolve` method calls the block with each tracked test and resolves those for which the block returns a truthy value.
The resolved test are not deleted from the configured [storage](#storage), they will have the attribute `resolved_at` set to the current time and will respond `true` to `resolved?`.
```ruby
FlakyTestTracker.resolver.resolve do |test|
# return truthy value to resolve the tracked test passed to block.
end
```
#### Examples
Resolve tests with the last failing occurrence that occurred 14 days ago.
```ruby
DAY_IN_SECOND = 86_400
FlakyTestTracker.resolver.resolve do |test|
test.finished_at < Time.now - 14 * DAY_IN_SECOND
end
```
It is useful to periodically resolve tests, this can be done using a [Rake](https://rubygems.org/gems/rake) task.
```ruby
# frozen_string_literal: true
namesapce :falky_test_tracker do
desc 'Resolve tests with the last failing occurence tracked 14 days ago'
task :resolve do
DAY_IN_SECOND = 86_400
FlakyTestTracker.resolver.resolve do |test|
test.finished_at < Time.now - 14 * DAY_IN_SECOND
end
end
end
```
### Configuration
The configuration is kept in the `FlakyTestTracker` module and is used to initialize the module [tracked](#track) and [resolver](#resolve) instances.
```ruby
FlakyTestTracker.configure do |config|
config.storage_type = :github_issue
config.storage_options = {
client: {
access_token: ENV['GITHUB_ACCESS_TOKEN']
},
repository: 'foo/bar',
labels: ['flaky test']
}
config.source_type = :github
config.source_options = {
repository: "foo/bar",
commit: ENV["CI_COMMIT"],
branch: ENV["CI_BRANCH"]
}
config.reporter = []
config.context = {
ci_build_id: ENV['CI_BUILD_ID'],
ci_build_url: ENV['CI_BUILD_URL']
}
config.verbose = true
config.pretend = false
end
```
You can access the configuration through the module `::configuration` method.
```ruby
FlakyTestTracker.configuration
# => #
```
#### Storage
The storage is responsible to persist tests.
You can use configure the storage by specifying the type, class, or class name of the store along with the options. The `storage_options` will be passed the storage class method `::build` as keyword arguments using `**`.
```ruby
FlakyTestTracker.configure do |config|
config.storage_type = :github_issue
# or `config.storage_class = FlakyTestTracker::Storage::GitHubIssueStorage`
# or `config.storage_class_name = "FlakyTestTracker::Storage::GitHubIssueStorage"`
config.storage_options = {}
end
```
Alternatively, you can also specify the storage instance directly.
```ruby
FlakyTestTracker.configure do |config|
config.storage = FlakyTestTracker::Storage::GitHubIssueStorage.build(**options)
end
```
You can access the configured storage through the method `#storage` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.storage
# => #
```
##### Storages
|Storage Type|Storage Class|Documentation|
|---|---|---|
|`:github_issue`|`FlakyTestTracker::Storage::GitHubIssueStorage`|...|
##### Custom Storage
You can use a custom storage, the storage class will need to have to the following interface:
```ruby
class MyStorage
def self.build(**options)
new(**options)
end
def initialize(**options)
# ...
end
# @return [Array]
def all
# ...
end
# @param [TestInput] test_input
# @return [Test]
def create(test_input)
# ...
end
# @param [String] id
# @param [TestInput] test_input
# @return [Test]
def update(id, test_input)
# ...
end
# @return [Test]
def delete(id)
# ...
end
end
```
#### Source
The source represents the current source code version on which tests are executed. It is used to resolves a test file location.
You can use configure the source by specifying the type, class, or class name, along with the options. The `source_options` will be passed the source class method `::build` as keyword arguments using `**`.
```ruby
FlakyTestTracker.configure do |config|
config.source_type = :github
# or `config.source_class = FlakyTestTracker::Source::GitHubSource`
# or `config.source_class_name = "FlakyTestTracker::Source::GitHubSource"`
config.source_options = {}
end
```
Alternatively, you can also specify the source instance directly.
```ruby
FlakyTestTracker.configure do |config|
config.source = FlakyTestTracker::Source::GitHubSource.build(**options)
end
```
You can access the configured source through the method `#source` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.source
# => #
```
##### Sources
|Source Type|Source Class|Documentation|
|---|---|---|
|`:github`|`FlakyTestTracker::Source::GitHubSource`|...|
##### Custom Source
You can use a custom source, the source class will need to have to the following interface:
```ruby
class MySource
def self.build(**options)
new(**options)
end
def initialize(**options)
# ...
end
# @param file_path [String]
# @param line_number [Integer]
# @return [URI]
def file_source_location_uri(file_path:, line_number:)
# ...
end
# @return [URI]
def source_uri
# ...
end
end
```
#### Reporter
The reporter can be used to alert your team on your preferred communication channel (email, Slack, Discord, etc.).
The [tracker](#tracker) will call the reporter `#tracked_tests` method with all the tests tracked, the [source](#source), and the [context](#context).
The [resolver](#resolver) will calls the reporter `#resolved_tests` method with all the tests resolved.
You can configure the reporter by specifying the class, or class name, along with the options. The `reporter_options` will be passed the reporter class method `::build` as keyword arguments using `**`.
```ruby
FlakyTestTracker.configure do |config|
config.reporter_class = MyReporter
# or `config.reporter_class = "MyReporter"`
config.reporter_options = {}
end
```
Alternatively, you can also specify the reporter instance directly.
```ruby
FlakyTestTracker.configure do |config|
config.reporter = MyReporter.build(**options)
end
```
You can access the configured reporter through the method `#reporter` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.reporter
# => #
```
##### Reporter
|Reporter Class|Documentation|
|---|---|
|`FlakyTestTracker::Reporter::CollectionReporter`|...|
##### Custom Reporter
You can use a custom reporter. The reporter class will need to respect the following interface:
```ruby
class MyReporter
def self.build(**options)
new(**options)
end
def initialize(**options)
# ...
end
# @param tests [Array]
# @param source [#file_source_location_uri, #source_uri]
# @param context [Hash]
def tracked_tests(tests:, source:, context:)
# ...
end
# @param tests [Array]
def resolved_tests(tests:)
# ...
end
end
```
If you inherit from `FlakyTestTracker::Reporter::BaseReporter`, you will only need to create the `::build` and override the methods you need.
```ruby
class MyReporter < FlakyTestTracker::Reporter::BaseReporter
def self.build(**options)
new(**options)
end
def initialize(**options)
# ...
end
end
```
#### Context
You can set a custom context that will be passed to your reporter `#tracked_tests` method. This is useful to identify the CI build in which the tests failed.
```ruby
FlakyTestTracker.configure do |config|
config.context = {}
end
```
You can access the configured context through the method `#context` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.context
# => {}
```
#### Verbose
When set to `true`, verbose messages will be print in the `STDOUT`.
```ruby
FlakyTestTracker.configure do |config|
config.verbose = true
end
```
You can access the configured verbose option through the method `#verbose` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.verbose
# => true
```
#### Pretend
When set to `true` the [tracker](#tracker) and [resolver](#resolver) will not make changes on the configured [storage](#storage). This is useful to test your configuration setup.
```ruby
FlakyTestTracker.configure do |config|
config.pretend = true
end
```
You can access the configured pretend option through the method `#pretend` of the `configuration` instance.
```ruby
FlakyTestTracker.configuration.pretend
# => true
```
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
### Documentation
The documentation is generated using [yard](https://yardoc.org/).
Build documentation
```shell
bundle exec yard doc
```
## Contributing
Bug reporter and pull requests are welcome on GitHub at https://github.com/masterT/flaky_test_tracker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/masterT/flaky_test_tracker/blob/main/CODE_OF_CONDUCT.md).
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
## Code of Conduct
Everyone interacting in the FlakyTestTracker project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [code of conduct](https://github.com/masterT/flaky_test_tracker/blob/main/CODE_OF_CONDUCT.md).