Class: Modsvaskr::TestsRunner

Inherits:
Object
  • Object
show all
Includes:
Logger
Defined in:
lib/modsvaskr/tests_runner.rb

Overview

Execute a bunch of tests on games

Instance Method Summary collapse

Methods included from Logger

#log, #out, #wait_for_user_enter

Constructor Details

#initialize(config, game) ⇒ TestsRunner

Constructor. Default values are for a standard Skyrim SE installation.

Parameters
  • config (Config): Main configuration

  • game (Game): Game for which we run tests



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/modsvaskr/tests_runner.rb', line 20

def initialize(config, game)
  @config = config
  @game = game
  # Parse tests suites
  @tests_suites = Dir.glob("#{__dir__}/tests_suites/*.rb").to_h do |tests_suite_file|
    tests_suite = File.basename(tests_suite_file, '.rb').to_sym
    require "#{__dir__}/tests_suites/#{tests_suite}.rb"
    [
      tests_suite,
      TestsSuites.const_get(tests_suite.to_s.split('_').collect(&:capitalize).join.to_sym).new(tests_suite, @game)
    ]
  end
  @tests_info_file = "#{@game.path}/Data/Modsvaskr/Tests/TestsInfo.json"
end

Instance Method Details

#clear_tests_for(tests_suite) ⇒ Object

Clear tests for a given tests suite

Parameters
  • tests_suite (Symbol): The tests suite



97
98
99
# File 'lib/modsvaskr/tests_runner.rb', line 97

def clear_tests_for(tests_suite)
  @tests_suites[tests_suite].clear_tests
end

#discover_tests_for(tests_suite) ⇒ Object

Return test names for a given tests suite

Parameters
  • tests_suite (Symbol): The tests suite

Result
  • Array<String>: Test names of this suite



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/modsvaskr/tests_runner.rb', line 49

def discover_tests_for(tests_suite)
  log "Discover tests for #{tests_suite}"
  discovered_tests = @tests_suites[tests_suite].discover_tests
  # Complete our tests information
  complete_info = tests_info
  discovered_tests.each do |test_name, test_info|
    complete_info[tests_suite] = {} unless complete_info.key?(tests_suite)
    complete_info[tests_suite][test_name] = test_info
  end
  update_tests_info(complete_info)
  discovered_tests.keys
end

#run(selected_tests) ⇒ Object

Run tests in a loop until they are all tested

Parameters
  • selected_tests (Hash<Symbol, Array<String> >): Ordered list of tests to be run, per tests suite



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/modsvaskr/tests_runner.rb', line 105

def run(selected_tests)
  # Test names (ordered) to be performed in game, per tests suite
  # Hash< Symbol, Array<String> >
  in_game_tests = {}
  selected_tests.each do |tests_suite, suite_selected_tests|
    if @tests_suites[tests_suite].respond_to?(:run_test)
      # Simple synchronous tests
      suite_selected_tests.each do |test_name|
        # Store statuses after each test just in case of crash
        set_statuses_for(tests_suite, [[test_name, @tests_suites[tests_suite].run_test(test_name)]])
      end
    end
    # We run the tests from the game itself.
    in_game_tests[tests_suite] = suite_selected_tests if @tests_suites[tests_suite].respond_to?(:in_game_tests_for)
  end
  return if in_game_tests.empty?

  # Keep track of the mapping between tests suites and in-game tests, per in-game tests suite.
  # Associated info is:
  # * *tests_suite* (Symbol): The tests suite that has subscribed to the statuses of some in-game tests of the in-game tests suite.
  # * *in_game_tests* (Array<String>): List of in-game tests that the tests suite is interested in.
  # * *selected_tests* (Array<String>): List of selected tests for which in-game tests are useful.
  # Hash< Symbol, Array< Hash< Symbol, Object > > >
  in_game_tests_subscriptions = {}
  # List of all in-game tests to perform, per in-game tests suite
  # Hash< Symbol, Array< String > >
  merged_in_game_tests = {}
  # Get the list of in-game tests we have to run and that we will monitor
  in_game_tests.each do |tests_suite, suite_selected_tests|
    in_game_tests_to_subscribe = @tests_suites[tests_suite].in_game_tests_for(suite_selected_tests)
    in_game_tests_to_subscribe.each do |in_game_tests_suite, selected_in_game_tests|
      selected_in_game_tests_downcase = selected_in_game_tests.map(&:downcase)
      in_game_tests_subscriptions[in_game_tests_suite] = [] unless in_game_tests_subscriptions.key?(in_game_tests_suite)
      in_game_tests_subscriptions[in_game_tests_suite] << {
        tests_suite:,
        in_game_tests: selected_in_game_tests_downcase,
        selected_tests: suite_selected_tests
      }
      merged_in_game_tests[in_game_tests_suite] = [] unless merged_in_game_tests.key?(in_game_tests_suite)
      merged_in_game_tests[in_game_tests_suite] = (merged_in_game_tests[in_game_tests_suite] + selected_in_game_tests_downcase).uniq
    end
  end
  in_game_tests_runner = InGameTestsRunner.new(@config, @game)
  in_game_tests_runner.run(merged_in_game_tests) do |in_game_tests_suite, in_game_tests_statuses|
    # This is a callback called for each in-game test status change.
    # Update the tests results based on what has been run in-game.
    # Find all tests suites that are subscribed to those in-game tests.
    # Be careful that updates can be given for in-game tests suites we were not expecting
    if in_game_tests_subscriptions.key?(in_game_tests_suite)
      in_game_tests_subscriptions[in_game_tests_suite].each do |tests_suite_subscription|
        selected_in_game_tests_statuses = in_game_tests_statuses.slice(*tests_suite_subscription[:in_game_tests])
        next if selected_in_game_tests_statuses.empty?

        tests_suite = @tests_suites[tests_suite_subscription[:tests_suite]]
        tests_suite.statuses = tests_suite.
          parse_auto_tests_statuses_for(tests_suite_subscription[:selected_tests], { in_game_tests_suite => selected_in_game_tests_statuses }).
          select { |(test_name, _test_status)| tests_suite_subscription[:selected_tests].include?(test_name) }
      end
    end
  end
end

#set_statuses_for(tests_suite, statuses) ⇒ Object

Set test statuses for a given tests suite

Parameters
  • tests_suite (Symbol): The tests suite

  • statuses (Array<[String, String]>): Ordered list of couples [test name, test status])



77
78
79
# File 'lib/modsvaskr/tests_runner.rb', line 77

def set_statuses_for(tests_suite, statuses)
  @tests_suites[tests_suite].statuses = statuses
end

#statuses_for(tests_suite) ⇒ Object

Get test statuses for a given tests suite

Parameters
  • tests_suite (Symbol): The tests suite

Result
  • Array<[String, String]>: Ordered list of couples [test name, test status]



68
69
70
# File 'lib/modsvaskr/tests_runner.rb', line 68

def statuses_for(tests_suite)
  @tests_suites[tests_suite].statuses
end

#test_info(tests_suite, test_name) ⇒ Object

Return test information

Parameters
  • tests_suite (Symbol): The tests suite

  • test_name (String): The test name

Result
  • Hash<Symbol,Object>: The test information (all properties are optional):

    • name (String): The test full name



89
90
91
# File 'lib/modsvaskr/tests_runner.rb', line 89

def test_info(tests_suite, test_name)
  tests_info.dig(tests_suite, test_name) || {}
end

#tests_suitesObject

Return tests suites

Result
  • Array<Symbol>: List of tests suites



39
40
41
# File 'lib/modsvaskr/tests_runner.rb', line 39

def tests_suites
  @tests_suites.keys.sort
end