Class: Cucumber::Distrib::Leader

Inherits:
Object
  • Object
show all
Includes:
DistribCore::Leader
Defined in:
lib/cucumber/distrib/leader.rb,
lib/cucumber/distrib/leader/reporter.rb,
lib/cucumber/distrib/leader/tests_provider.rb,
lib/cucumber/distrib/leader/cucumber_helper.rb

Overview

Interface exposed over the network that Workers connect to in order to receive test file names and report back the results to.

Transport used is [DRb](rubydoc.info/stdlib/drb/DRb).

Defined Under Namespace

Classes: CucumberHelper, LocalEventBus, Reporter, TestsProvider

Constant Summary collapse

DRB_SERVER_URL =

Used to interpolate with leader IP in order to generate the actual DRb server URL.

'druby://%s:8788'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(queue, profiles, reporter, runtime) ⇒ Leader

Returns a new instance of Leader.



192
193
194
195
196
197
198
# File 'lib/cucumber/distrib/leader.rb', line 192

def initialize(queue, profiles, reporter, runtime)
  @queue = queue
  @profiles = profiles
  @reporter = reporter
  @runtime = runtime
  @run_started = false
end

Instance Attribute Details

#non_example_exceptionObject (readonly)

Returns the value of attribute non_example_exception.



190
191
192
# File 'lib/cucumber/distrib/leader.rb', line 190

def non_example_exception
  @non_example_exception
end

#profilesObject (readonly)

Returns the value of attribute profiles.



190
191
192
# File 'lib/cucumber/distrib/leader.rb', line 190

def profiles
  @profiles
end

Class Method Details

.filter_provided_tests(tests:, profiles:, paths:) ⇒ Object

Filter list of provided tests (scenarios/test cases), to include only those matching selected profiles.



109
110
111
112
113
114
# File 'lib/cucumber/distrib/leader.rb', line 109

def filter_provided_tests(tests:, profiles:, paths:)
  return tests if tests.empty?

  locations = filtered_test_cases(profiles:, paths:)
  tests.intersection(locations)
end

.start_service(profiles:, paths: []) ⇒ Integer

Starts the DRb server with exposed instance of the class. Prepares queue of tests, starts Watchdog thread.

rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity

Parameters:

  • profiles (Array<String>)

    a list of profiles for Leader and workers

  • paths (Array<String>) (defaults to: [])

    a list of directories from which list of local tests will be build

Returns:

  • (Integer)

    Exit code

See Also:

  • DistribCore::Leader::Watchdog


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/cucumber/distrib/leader.rb', line 54

def start_service(profiles:, paths: [])
  tests = ::DistribCore::Leader::QueueBuilder.tests

  # Workaround over existing tests that pass list of files not scenarios.
  unless ENV['CUCUMBER_DISTRIB_FOLDER']
    tests = filter_provided_tests(
      tests:,
      profiles:,
      paths:
    )
  end

  queue = ::DistribCore::Leader::QueueWithLease.new(tests)

  logger.info "#{tests.count} tests have been enqueued"

  # We need to initialize Cucumber::Runtime to make reporters work.
  runtime = prepare_runtime(profiles)
  reporter = Cucumber::Distrib::Leader::Reporter.new(runtime)

  leader = new(queue, profiles, reporter, runtime)

  watchdog = ::DistribCore::Leader::Watchdog.new(queue)
  watchdog.start

  msg = Cucumber::Messages::Envelope.new(
    meta: Cucumber::CreateMeta.create_meta('cucumber-ruby', Cucumber::VERSION)
  )

  meta_event = Cucumber::Distrib::Events::Envelope.new(msg)
  runtime.configuration.event_bus.broadcast(meta_event)

  DRb.start_service(DRB_SERVER_URL % '0.0.0.0', leader, Cucumber::Distrib.configuration.drb)
  logger.info 'Leader ready'
  ::DistribCore::Metrics.queue_exposed
  DRb.thread.join

  reporter.report_test_run_finished
  Cucumber::Distrib.configuration.on_finish&.call

  failed = runtime.failure? || watchdog.failed? || leader.non_example_exception
  count_mismatch = (queue.size + queue.completed_size != tests.count)

  # NOTE: runtime.features stays empty for the whole run. It may affect statistics.
  if Cucumber.wants_to_quit || failed || ::DistribCore::ReceivedSignals.any? || count_mismatch
    print_failure_status(runtime, watchdog, leader, queue, count_mismatch)
    Kernel.exit(::DistribCore::ReceivedSignals.any? ? ::DistribCore::ReceivedSignals.exit_code : 1)
  else
    logger.info "Build succeeded. Tests processed: #{queue.completed_size}"
  end
end

Instance Method Details

#next_test_to_runString

Get the next test from the queue.

Returns:

  • (String)


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/cucumber/distrib/leader.rb', line 203

drb_callable def next_test_to_run
  logger.debug 'Next test requested'

  unless run_started?
    @run_started = true
    reporter.report_test_run_started
    logger.debug 'Test run started'
  end

  ::DistribCore::Metrics.test_taken

  queue.lease.tap do |test|
    logger.debug "Serving #{test}"
  end
end