Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Every generated project comes with:
- **Page Object Model** — Base page and component classes with example pages
- **Test examples** — Working login tests against the [Raider Test Store](https://raider-test-site.onrender.com/)
- **Allure reporting** — Pre-configured with screenshot capture on failure
- **Raider reporting** — RSpec projects include [raider_reporter](https://github.com/RaiderHQ/raider_reporter), which writes results to `raider-results/` and uploads runs when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set
- **GitHub Actions CI** — Ready-to-use test pipeline
- **Rake tasks** — Default, smoke, and regression tasks with tag-based filtering
- **Retry support** — RSpec retry with configurable retry count via `RETRY_COUNT` env var
Expand Down
11 changes: 11 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Release Process Documentation

## Release Notes

### 3.3.0

- Generated RSpec projects now include `raider_reporter`: results are written to `raider-results/` and uploaded when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set. Allure is still produced. Cucumber projects are unchanged.
- Screenshots (Allure too) are now taken only when an example fails, and are attached to both Allure and Raider.
- Generated GitHub CI now runs on push (main, master), pull requests and manual dispatch, passes the Raider settings to RSpec runs and uploads `raider-results/` as an artifact.
- Fixed the generated Gemfile `ruby_raider` pin so it follows the gem's own major.minor version.

---

## Overview

Ruby Raider uses a **fully automated release process**. You only need to run a single command, and everything else happens automatically via GitHub Actions.
Expand Down
5 changes: 5 additions & 0 deletions lib/generators/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ def selenium_based?
args.include?('selenium')
end

def ruby_raider_version_requirement
major, minor = File.read(File.expand_path('../version', __dir__)).strip.split('.')
"~> #{major}.#{minor}"
end

private

def _initializer
Expand Down
18 changes: 18 additions & 0 deletions lib/generators/infrastructure/templates/github.tt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: <%- if framework == 'cucumber' -%>Cucumber Tests<%- else -%>Rspec Tests<%- end -%>

on:
push:
branches: [ main, master ]
pull_request:
workflow_dispatch:
inputs:
browser:
Expand Down Expand Up @@ -37,6 +40,21 @@ jobs:
run: <%- if framework == 'cucumber' -%>bundle exec cucumber features --format pretty<%- else -%>bundle exec rspec spec --format documentation<%- end %>
env:
HEADLESS: true
<%- unless framework == 'cucumber' -%>
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
<%- end -%>

<%- unless framework == 'cucumber' -%>
- name: Upload Raider results
uses: actions/upload-artifact@v4
if: always()
with:
name: raider-results
path: raider-results/
if-no-files-found: ignore

<%- end -%>

- name: Get Allure history
uses: actions/checkout@v2
Expand Down
28 changes: 26 additions & 2 deletions lib/generators/infrastructure/templates/github_appium.tt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Appium Tests

on:
push:
branches: [ main ]
branches: [ main, master ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
<%- if ios? || cross_platform? -%>
Expand Down Expand Up @@ -52,6 +52,18 @@ jobs:
<%- end -%>
env:
APP_PATH: ${{ github.workspace }}/apps/RaiderTestApp.app
<%- unless cucumber? -%>
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}

- name: Upload Raider results
uses: actions/upload-artifact@v4
if: always()
with:
name: raider-results-ios
path: raider-results/
if-no-files-found: ignore
<%- end -%>
<%- end -%>

<%- if android? || cross_platform? -%>
Expand Down Expand Up @@ -101,4 +113,16 @@ jobs:
<%- end -%>
env:
APP_PATH: ${{ github.workspace }}/apps/app-release.apk
<%- unless cucumber? -%>
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}

- name: Upload Raider results
uses: actions/upload-artifact@v4
if: always()
with:
name: raider-results-android
path: raider-results/
if-no-files-found: ignore
<%- end -%>
<%- end -%>
3 changes: 2 additions & 1 deletion lib/generators/templates/common/gemfile.tt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ gem 'parallel_tests'
gem 'rake'
gem 'reek'
<%- if rspec? -%>
gem 'raider_reporter', '~> 0.2'
gem 'rspec-retry'
<%- end -%>
gem '<%= framework %>'
Expand All @@ -30,7 +31,7 @@ gem 'rubocop'
<%- if rspec? -%>
gem 'rubocop-rspec'
<%- end -%>
gem 'ruby_raider', '~> 1.1.0'
gem 'ruby_raider', '<%= ruby_raider_version_requirement %>'
<%- if selenium_based? %>
gem 'selenium-webdriver'
<%- end -%>
Expand Down
1 change: 1 addition & 0 deletions lib/generators/templates/common/git_ignore.tt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
allure-results
<%- if rspec? -%>
raider-results
spec/examples.txt
<%- end -%>
17 changes: 17 additions & 0 deletions lib/generators/templates/common/read_me.tt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ raider g steps [NAME] # Create step definitions
raider g scaffold [NAME] # Create page + test + steps
```

<%- if rspec? -%>
## Reporting

Every run writes machine-readable results to `raider-results/` (including `run.json`), next to the usual Allure results.
Allure reports are still produced.

To upload runs to Raider, set these environment variables before running the suite:

```bash
export RAIDER_TOKEN=your-token
export RAIDER_ENDPOINT=https://your-raider-endpoint
```

Without `RAIDER_TOKEN`, nothing is uploaded and the suite output is unchanged. Failure screenshots are attached to both
Allure and Raider. See the [raider_reporter README](https://github.com/RaiderHQ/raider_reporter) for details.

<%- end -%>
### Sponsors

This project is tested with BrowserStack.
6 changes: 3 additions & 3 deletions lib/generators/templates/helpers/partials/screenshot.tt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<% if selenium_based? %>
screenshot = driver.save_screenshot("#{temp_folder}/#{example_name}.png")
screenshot = driver.save_screenshot(screenshot_path)
<% elsif watir? %>
screenshot = browser.screenshot.save("#{temp_folder}/#{example_name}.png")
screenshot = browser.screenshot.save(screenshot_path)
<% else %>
screenshot = driver.screenshot("#{temp_folder}/#{example_name}.png")
screenshot = driver.screenshot(screenshot_path)
<% end %>
15 changes: 10 additions & 5 deletions lib/generators/templates/helpers/spec_helper.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ require 'axe-rspec'
<%- end -%>
require 'rspec'
require 'rspec/retry'
require 'digest'
require 'raider_reporter/rspec'
require 'tmpdir'
require_relative 'allure_helper'
<%- if watir? -%>
Expand All @@ -21,7 +23,8 @@ module SpecHelper
config.verbose_retry = true
config.display_try_failure_messages = true
config.default_retry_count = ENV.fetch('RETRY_COUNT', 0).to_i
config.formatter = AllureHelper.formatter
config.add_formatter(AllureHelper.formatter)
config.add_formatter(RaiderReporter::RSpec::Formatter)
<%- if watir? -%>
config.include(BrowserHelper)
<%- else -%>
Expand Down Expand Up @@ -53,10 +56,12 @@ module SpecHelper
example_name = example.description
if example.exception
@_exception = example.exception
end
Dir.mktmpdir do |temp_folder|
<%= partial('screenshot', strip: true) %>
AllureHelper.add_screenshot(example_name, screenshot)
Dir.mktmpdir do |temp_folder|
screenshot_path = "#{temp_folder}/#{example_name}.png"
<%= partial('screenshot', strip: true) %>
AllureHelper.add_screenshot(example_name, screenshot)
RaiderReporter.attach('screenshot', screenshot_path, type: :png)
end
end
<%= partial('quit_driver', strip: true) %>
end
Expand Down
1 change: 1 addition & 0 deletions lib/generators/templates/helpers/test_helper.tt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module TestHelper
<%- end -%>
<%- end -%>
Dir.mktmpdir do |temp_folder|
screenshot_path = "#{temp_folder}/#{example_name}.png"
<%= partial('screenshot', strip: true) %>
<%- if allure_reporter? -%>
AllureHelper.add_screenshot(example_name, screenshot)
Expand Down
2 changes: 1 addition & 1 deletion lib/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.1
3.3.0
85 changes: 85 additions & 0 deletions spec/integration/content/ci_content_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,106 @@
end
end

shared_examples 'github triggers' do |project_name, file|
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }

let(:triggers) { YAML.safe_load(pipeline)[true] }

it 'triggers on push to main and master' do
expect(triggers['push']['branches']).to include('main', 'master')
end

it 'triggers on pull_request' do
expect(triggers).to have_key('pull_request')
end

it 'triggers on workflow_dispatch' do
expect(triggers).to have_key('workflow_dispatch')
end
end

shared_examples 'github raider wiring' do |project_name, file|
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }

let(:steps) { YAML.safe_load(pipeline)['jobs'].values.flat_map { |job| job['steps'] } }

let(:test_steps) do
steps.select { |step| step['run'].to_s.include?('rspec') || step['with'].to_h['script'].to_s.include?('rspec') }
end

it 'passes Raider settings to every test step' do
expect(test_steps).not_to be_empty
test_steps.each do |step|
expect(step['env']).to include('RAIDER_TOKEN' => '${{ secrets.RAIDER_TOKEN }}',
'RAIDER_ENDPOINT' => '${{ vars.RAIDER_ENDPOINT }}')
end
end

it 'uploads raider-results as an artifact even on failure in every job' do
uploads = steps.select { |step| step['uses'] == 'actions/upload-artifact@v4' }
expect(uploads.size).to eq(YAML.safe_load(pipeline)['jobs'].size)
uploads.each do |upload|
expect(upload['with']['path']).to eq('raider-results/')
expect(upload['if']).to eq('always()')
end
end
end

shared_examples 'github without raider wiring' do |project_name, file|
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }

it 'has no Raider settings or artifact' do
expect(pipeline).not_to include('RAIDER_')
expect(pipeline).not_to include('raider-results')
end
end

shared_examples 'github allure steps' do |project_name|
subject(:pipeline) { read_generated(project_name, '.github/workflows/test_pipeline.yml') }

it 'keeps the Allure steps' do
expect(pipeline).to include('simple-elf/allure-report-action', 'peaceiris/actions-gh-pages')
end
end

context 'with rspec and selenium' do
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
include_examples 'valid github pipeline', name
include_examples 'github rspec pipeline', name
include_examples 'github triggers', name, 'test_pipeline.yml'
include_examples 'github raider wiring', name, 'test_pipeline.yml'
include_examples 'github allure steps', name
end

context 'with cucumber and selenium' do
name = "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
include_examples 'valid github pipeline', name
include_examples 'github cucumber pipeline', name
include_examples 'github triggers', name, 'test_pipeline.yml'
include_examples 'github without raider wiring', name, 'test_pipeline.yml'
include_examples 'github allure steps', name
end

context 'with rspec and watir' do
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
include_examples 'valid github pipeline', name
include_examples 'github rspec pipeline', name
include_examples 'github triggers', name, 'test_pipeline.yml'
include_examples 'github raider wiring', name, 'test_pipeline.yml'
include_examples 'github allure steps', name
end

%w[android ios cross_platform].each do |automation|
context "with rspec and #{automation}" do
name = "#{FrameworkIndex::RSPEC}_#{automation}"
include_examples 'github triggers', name, 'appium_pipeline.yml'
include_examples 'github raider wiring', name, 'appium_pipeline.yml'
end

context "with cucumber and #{automation}" do
name = "#{FrameworkIndex::CUCUMBER}_#{automation}"
include_examples 'github triggers', name, 'appium_pipeline.yml'
include_examples 'github without raider wiring', name, 'appium_pipeline.yml'
end
end
end
13 changes: 12 additions & 1 deletion spec/integration/content/common_content_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@
it 'uses documentation format' do
expect(rspec_file).to include('--format documentation')
end

it 'leaves the raider formatter to spec_helper, since a command-line --format replaces .rspec formatters' do
expect(rspec_file).not_to include('RaiderReporter')
end
end

shared_examples 'no rspec dotfile' do |project_name|
Expand All @@ -109,6 +113,10 @@
it 'includes spec/examples.txt' do
expect(gitignore).to include('spec/examples.txt')
end

it 'includes raider-results' do
expect(gitignore).to include('raider-results')
end
end

shared_examples 'non-rspec gitignore' do |project_name|
Expand All @@ -121,6 +129,10 @@
it 'does not include spec/examples.txt' do
expect(gitignore).not_to include('spec/examples.txt')
end

it 'does not include raider-results' do
expect(gitignore).not_to include('raider-results')
end
end

# --- Spec helper retry config (C4) ---
Expand Down Expand Up @@ -220,5 +232,4 @@
it_behaves_like 'gemfile without rspec-retry', name
it_behaves_like 'cucumber config with retry', name
end

end
Loading
Loading