teuton 2.3.11 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +44 -13
  3. data/docs/CHANGELOG.md +0 -13
  4. data/docs/changelog/todo.md +18 -0
  5. data/docs/changelog/v2.4.md +6 -2
  6. data/docs/dsl/execution/export.md +9 -15
  7. data/docs/dsl/execution/show.md +22 -7
  8. data/docs/ideas/{ideas.md → todo.md} +8 -16
  9. data/docs/learn/01-target.md +14 -43
  10. data/docs/learn/02-config.md +20 -37
  11. data/docs/learn/03-remote_hosts.md +20 -1
  12. data/docs/learn/04-new_test.md +4 -4
  13. data/docs/learn/05-use.md +3 -4
  14. data/docs/learn/06-debug.md +6 -9
  15. data/docs/learn/07-log.md +14 -14
  16. data/docs/learn/08-readme.md +4 -4
  17. data/docs/learn/13-include.md +13 -6
  18. data/docs/learn/14-alias.md +14 -8
  19. data/docs/learn/README.md +7 -7
  20. data/lib/teuton/case_manager/case/case.rb +1 -5
  21. data/lib/teuton/case_manager/case/dsl/expect.rb +2 -4
  22. data/lib/teuton/case_manager/case/dsl/log.rb +1 -2
  23. data/lib/teuton/case_manager/case/dsl/send.rb +4 -2
  24. data/lib/teuton/case_manager/case/play.rb +1 -2
  25. data/lib/teuton/case_manager/case/runner.rb +6 -7
  26. data/lib/teuton/case_manager/case_manager.rb +15 -11
  27. data/lib/teuton/case_manager/check_cases.rb +5 -7
  28. data/lib/teuton/case_manager/dsl.rb +1 -1
  29. data/lib/teuton/case_manager/export_manager.rb +13 -15
  30. data/lib/teuton/case_manager/hall_of_fame.rb +20 -16
  31. data/lib/teuton/case_manager/main.rb +1 -2
  32. data/lib/teuton/case_manager/report.rb +3 -3
  33. data/lib/teuton/report/formatter/base_formatter.rb +6 -7
  34. data/lib/teuton/report/formatter/{array_formatter.rb → default/array.rb} +44 -9
  35. data/lib/teuton/report/formatter/default/colored_text.rb +7 -0
  36. data/lib/teuton/report/formatter/default/html.rb +24 -0
  37. data/lib/teuton/report/formatter/default/json.rb +15 -0
  38. data/lib/teuton/report/formatter/{txt_formatter.rb → default/txt.rb} +4 -3
  39. data/lib/teuton/report/formatter/{xml_formatter.rb → default/xml.rb} +10 -4
  40. data/lib/teuton/report/formatter/default/yaml.rb +15 -0
  41. data/lib/teuton/report/formatter/formatter.rb +54 -0
  42. data/lib/teuton/report/formatter/moodle_csv_formatter.rb +4 -10
  43. data/lib/teuton/report/formatter/{resume_array_formatter.rb → resume/array.rb} +4 -7
  44. data/lib/teuton/report/formatter/resume/colored_text.rb +7 -0
  45. data/lib/teuton/report/formatter/{resume_html_formatter.rb → resume/html.rb} +7 -9
  46. data/lib/teuton/report/formatter/{resume_json_formatter.rb → resume/json.rb} +4 -4
  47. data/lib/teuton/report/formatter/{resume_txt_formatter.rb → resume/txt.rb} +4 -6
  48. data/lib/teuton/report/formatter/{resume_yaml_formatter.rb → resume/yaml.rb} +4 -3
  49. data/lib/teuton/report/report.rb +60 -43
  50. data/lib/teuton/report/show.rb +38 -24
  51. data/lib/teuton/version.rb +1 -1
  52. metadata +32 -33
  53. data/lib/teuton/case_manager/show.rb +0 -24
  54. data/lib/teuton/report/close.rb +0 -38
  55. data/lib/teuton/report/formatter/csv_formatter.rb +0 -25
  56. data/lib/teuton/report/formatter/formatter_factory.rb +0 -79
  57. data/lib/teuton/report/formatter/html_formatter.rb +0 -57
  58. data/lib/teuton/report/formatter/json_formatter.rb +0 -12
  59. data/lib/teuton/report/formatter/list_formatter.rb +0 -65
  60. data/lib/teuton/report/formatter/resume_list_formatter.rb +0 -62
  61. data/lib/teuton/report/formatter/yaml_formatter.rb +0 -15
@@ -1,6 +1,6 @@
1
1
  [<< back](README.md)
2
2
 
3
- # Example: 07-readme
3
+ # Example: readme
4
4
 
5
5
  Create README files (with test instructions) from our test definition.
6
6
 
@@ -35,15 +35,15 @@ There exists some `readme` instructions after `group` and `target` lines.
35
35
  To generate automatically a README file from previous test, execute this:
36
36
 
37
37
  ```
38
- teuton readme example/learn-08-readme > example/learn-08-readme/README.md
38
+ teuton readme example/08-readme > example/08-readme/README.md
39
39
  ```
40
40
 
41
41
  ## Result
42
42
 
43
- **Let's see the output**: Content of `example/learn-08-readme/README.md` file.
43
+ **Let's see the output**: Content of `example/08-readme/README.md` file.
44
44
 
45
45
  ---
46
- # learn-08-readme
46
+ # 08-readme
47
47
 
48
48
  ## Customize readme output
49
49
 
@@ -2,13 +2,17 @@
2
2
 
3
3
  # Example: 13-include
4
4
 
5
- Until now, all the tests we have seen came with a configuration file (`config.yaml`) that contained all the parameters that will later be used in the test. It is also possible to have the information distributed among several configuration files.
5
+ Use `tt-include` to include several config files into your main config file.
6
+
7
+ ## Explanation
8
+
9
+ Until now, all the examples we have seen use one configuration file (`config.yaml`) that contain all the parameters required by the test. It is possible to save configuration distributed among several files.
6
10
 
7
11
  Suppose we have the following file structure.
8
12
 
9
13
  ```
10
14
  ├── config.yaml
11
- ├── include_this_files
15
+ ├── moreconfigfiles
12
16
  │   ├── 02
13
17
  │   │   └── file02.yaml
14
18
  │   ├── file01.yaml
@@ -16,15 +20,15 @@ Suppose we have the following file structure.
16
20
  └── start.rb
17
21
  ```
18
22
 
19
- `config.yaml` will be the main config file. Using `tt_include` parameter, we define a folder where the rest of the configuration files will be.
23
+ `config.yaml` will be the main config file. We have defined `tt_include` parameter with a folder wich contains more configuration files.
20
24
 
21
- In this example the contents of the files in the include_this_files folder will be included in the configuration:
25
+ In this example the contents of all files in `moreconfigfiles` folder will be included when reading the config parameters:
22
26
 
23
27
  ```yaml
24
28
  ---
25
29
  # Fiel: config.yaml
26
30
  :global:
27
- :tt_include: include_this_files
31
+ :tt_include: moreconfigfiles
28
32
  :cases:
29
33
  ```
30
34
 
@@ -41,19 +45,22 @@ CASE RESULTS
41
45
  +------+---------+-------+-------+
42
46
  ```
43
47
 
44
- Config files into `include_this_files` folder:
48
+ Config files into `moreconfigfiles` folder:
45
49
 
46
50
  ```yaml
51
+ # moreconfigfiles/file01.yaml
47
52
  :tt_members: file01
48
53
  :username: root
49
54
  ```
50
55
 
51
56
  ```yaml
57
+ # moreconfigfiles/02/file02.yaml
52
58
  :tt_members: file02
53
59
  :username: quigon
54
60
  ```
55
61
 
56
62
  ```yaml
63
+ # moreconfigfiles/file03.yml
57
64
  :tt_members: file03
58
65
  :username: vader
59
66
  ```
@@ -2,7 +2,11 @@
2
2
 
3
3
  # Example: 14-alias
4
4
 
5
- Supongamos que tenemos un test como el siguiente:
5
+ By using aliases we can adapt a configuration file, so that it can be used with many different tests.
6
+
7
+ ## Exanation
8
+
9
+ Suppose we have a test like the following:
6
10
 
7
11
  ```ruby
8
12
  group "Using alias" do
@@ -16,14 +20,14 @@ group "Using alias" do
16
20
  end
17
21
  ```
18
22
 
19
- Tenemos sólo 2 targets pero podríamos tener muchos más.
23
+ > REMEMBER:
24
+ > * We only have 2 targets but we could have many more.
25
+ > * `_username` is equivalent to `get(:username)`
20
26
 
21
- > Recordemos que `_username` es equivalente a `get(:username)`
22
-
23
- Sabemos que el fichero de configuración debe definir los valores para los parámetros `super` y `username`. Queremos aprovechar un fichero de configuración que ya teníamos de otro test, pero tiene el siguiente contenido:
27
+ Our test requires the `super` parameter but the configuration file has named it as `superuser`. Our configuration file define values for `supername` and `username` parameters. Let's see:
24
28
 
25
29
  ```yaml
26
- # Version 1
30
+ # First version
27
31
  # File: config.yaml
28
32
  global:
29
33
  cases:
@@ -32,10 +36,10 @@ cases:
32
36
  username: obiwan
33
37
  ```
34
38
 
35
- Podemos comprobar que nuestro test require el parámetro `super` pero el fichero de configuración lo ha nombrado como `superuser`.
39
+ We would like to take advantage of a configuration file that we already had from another test, without big changes. So we add an `alias`:
36
40
 
37
41
  ```yaml
38
- # Version 2
42
+ # Alias Version
39
43
  # File: config.yaml
40
44
  alias:
41
45
  super: :superuser
@@ -45,3 +49,5 @@ cases:
45
49
  superuser: root
46
50
  username: obiwan
47
51
  ```
52
+
53
+ Now our test will work correctly. Calling `get(:super)` will return the same value as doing `get(:superuser).
data/docs/learn/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
 
2
2
  [<< back](../../README.md)
3
3
 
4
- 1. [Learning](#learning)
5
- 2. [Examples](#examples)
6
- 3. [Videos](#videos)
4
+ * [Learning](#learning)
5
+ * [Examples](#examples)
6
+ * [Videos](#videos)
7
7
 
8
8
  # Learning
9
9
 
@@ -21,16 +21,16 @@ Learn how to use Teuton language to write your own tests:
21
21
  - [11 - Moodle ID](11-moodle_id.md)
22
22
  - [12 - Get vars](12-get_vars.md)
23
23
  - [13 - Include](13-include.md)
24
- - Example 14 - Alias
25
- - Example 15 - Macros
26
- - [Example 16 - Exit codes](16-exit_codes.md)
24
+ - [14 - Alias](14-alias.md)
25
+ - 15 - Macros
26
+ - [16 - Exit codes](16-exit_codes.md)
27
27
  - [Videos](videos.md)
28
28
 
29
29
  # Examples
30
30
 
31
31
  More examples
32
32
  * Let's see examples at [teuton-tests](https://github.com/dvarrui/teuton-tests) GitHub repository.
33
- * Ask us by email at `teuton.software@protonmail.com` or Twitter at `@SoftwareTeuton`.
33
+ * Ask us by email at `teuton.software@protonmail.com`.
34
34
  * [ES - CHAPI19: Teuton demo](https://github.com/dvarrui/proyectos-de-ejemplo/tree/master/charlas/teuton)
35
35
 
36
36
  # Videos
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../../application"
4
4
  require_relative "../../report/report"
5
+ require_relative "../../report/show"
5
6
  require_relative "../utils"
6
7
  require_relative "main"
7
8
  require_relative "result/result"
@@ -17,7 +18,6 @@ require_relative "builtin/main"
17
18
  # * grade
18
19
  # * members
19
20
  # * skip
20
- # * show
21
21
  # * read_filename ???
22
22
  class Case
23
23
  include DSL
@@ -100,10 +100,6 @@ class Case
100
100
 
101
101
  alias skip? skip
102
102
 
103
- def show
104
- @report.show
105
- end
106
-
107
103
  private
108
104
 
109
105
  def read_filename(filename)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "colorize"
4
-
5
3
  module DSL
6
4
  # expect <condition>, :weight => <value>
7
5
  def expect(input, args = {})
@@ -10,7 +8,7 @@ module DSL
10
8
  elsif input.instance_of?(String) || input.instance_of?(Regexp) || input.instance_of?(Array)
11
9
  expect_any input
12
10
  else
13
- puts "[TypeError] expect #{input} (#{input.class})"
11
+ puts Rainbow("[TypeError] expect #{input} (#{input.class})").red
14
12
  end
15
13
  end
16
14
 
@@ -30,7 +28,7 @@ module DSL
30
28
  app = Application.instance
31
29
  c = app.letter[:bad]
32
30
  c = app.letter[:good] if cond
33
- verbose c.colorize(:green)
31
+ verbose Rainbow(c).green
34
32
  end
35
33
 
36
34
  def expect_any(input, args = {})
@@ -1,5 +1,4 @@
1
- # frozen_string_literal: true
2
-
1
+ require "rainbow"
3
2
  ##
4
3
  # Define DSL#log function
5
4
  module DSL
@@ -37,9 +37,11 @@ module DSL
37
37
  Net::SFTP.start(ip, username, password: password, port: port) do |sftp|
38
38
  sftp.upload!(localfilepath, remotefilepath)
39
39
  end
40
- verboseln("=> [ OK ] #{(get(:tt_members)[0, 15]).ljust(16)} : #{remotefilepath}")
40
+ msg = Rainbow("[ OK ] #{(get(:tt_members)[0, 15]).ljust(16)} : #{remotefilepath}").green
41
+ verboseln(msg)
41
42
  rescue
42
- verboseln("=> [ERROR] #{(get(:tt_members)[0, 15]).ljust(16)} : scp #{localfilepath} => #{remotefilepath}")
43
+ msg = Rainbow("[ERROR] #{(get(:tt_members)[0, 15]).ljust(16)} : scp #{localfilepath} => #{remotefilepath}").red
44
+ verboseln(msg)
43
45
  end
44
46
  end
45
47
 
@@ -9,10 +9,9 @@
9
9
  class Case
10
10
  def play
11
11
  if skip?
12
- verbose "Skipping case <#{@config.get(:tt_members)}>\n"
12
+ verbose Rainbow("S").green
13
13
  return false
14
14
  end
15
- # TODO: Delete old reports???
16
15
  start_time = Time.now
17
16
  if get(:tt_sequence) == true
18
17
  play_in_sequence
@@ -11,11 +11,14 @@ class Case
11
11
  ip = @config.get("#{host}_ip".to_sym)
12
12
 
13
13
  if protocol.to_s.downcase == "local" || host.to_s == "localhost"
14
- run_cmd_localhost # Protocol force => local
14
+ # Protocol force => local
15
+ run_cmd_localhost
15
16
  elsif protocol.to_s.downcase == "ssh"
16
- run_cmd_remote_ssh(host) # Protocol force => ssh
17
+ # Protocol force => ssh
18
+ run_cmd_remote_ssh(host)
17
19
  elsif protocol.to_s.downcase == "telnet"
18
- run_cmd_remote_telnet(host) # Protocol force => telnet
20
+ # Protocol force => telnet
21
+ run_cmd_remote_telnet(host)
19
22
  elsif ip.to_s.downcase == "localhost" || ip.to_s.include?("127.0.0.")
20
23
  run_cmd_localhost
21
24
  elsif ip == "NODATA"
@@ -101,17 +104,14 @@ class Case
101
104
  rescue Errno::EHOSTUNREACH
102
105
  @sessions[hostname] = :nosession
103
106
  @conn_status[hostname] = :host_unreachable
104
- verbose Rainbow(Application.instance.letter[:error]).red.bright
105
107
  log("Host #{ip} unreachable!", :error)
106
108
  rescue Net::SSH::AuthenticationFailed
107
109
  @sessions[hostname] = :nosession
108
110
  @conn_status[hostname] = :error_authentication_failed
109
- verbose Rainbow(Application.instance.letter[:error]).red.bright
110
111
  log("SSH::AuthenticationFailed!", :error)
111
112
  rescue Net::SSH::HostKeyMismatch
112
113
  @sessions[hostname] = :nosession
113
114
  @conn_status[hostname] = :host_key_mismatch
114
- verbose Rainbow(Application.instance.letter[:error]).red.bright
115
115
  log("SSH::HostKeyMismatch!", :error)
116
116
  log("* The destination server's fingerprint is not matching " \
117
117
  "what is in your local known_hosts file.", :error)
@@ -121,7 +121,6 @@ class Case
121
121
  rescue => e
122
122
  @sessions[hostname] = :nosession
123
123
  @conn_status[hostname] = :error
124
- verbose Rainbow(Application.instance.letter[:error]).red.bright
125
124
  log("[#{e.class}] SSH on <#{username}@#{ip}>" \
126
125
  " exec: #{@action[:command]}", :error)
127
126
  end
@@ -1,13 +1,12 @@
1
- # frozen_string_literal: true
2
-
1
+ require "rainbow"
3
2
  require "singleton"
4
3
  require_relative "../application"
5
4
  require_relative "../report/report"
5
+ require_relative "../report/show"
6
6
  require_relative "../utils/configfile_reader"
7
7
  require_relative "case/case"
8
8
  require_relative "export_manager"
9
9
  require_relative "main"
10
- require_relative "utils"
11
10
 
12
11
  # This class does all the job
13
12
  # Organize the hole job, sending orders to others classes
@@ -18,13 +17,11 @@ require_relative "utils"
18
17
  # * case_manager/export
19
18
  # * case_manager/hall_of_fame
20
19
  # * case_manager/report
21
- # * case_manager/show
22
20
  class CaseManager
23
21
  include Singleton
24
22
  include Utils
23
+ attr_reader :report, :cases
25
24
 
26
- ##
27
- # Initialize CaseManager
28
25
  def initialize
29
26
  @cases = []
30
27
  @report = Report.new(0)
@@ -50,12 +47,11 @@ class CaseManager
50
47
  # @param args (Hash) Export options
51
48
  def export(args = {})
52
49
  if args.class != Hash
53
- puts "[ERROR] CaseManager#export: Argument = <#{args}>, " \
54
- "class = #{args.class}"
55
- puts " Usage: export :format => :colored_text"
50
+ puts "[ERROR] CaseManager#export: Argument error!"
51
+ puts " Source : export #{args} <#{args.class}>"
52
+ puts " Usage : export format: 'txt'"
56
53
  raise "[ERROR] CaseManager#export: Argument error!"
57
54
  end
58
- # Export report files
59
55
  ExportManager.run(@report, @cases, args)
60
56
  end
61
57
 
@@ -65,8 +61,16 @@ class CaseManager
65
61
  def send(args = {})
66
62
  threads = []
67
63
  puts ""
68
- puts "[INFO] Sending files...#{args}"
64
+ # puts Rainbow("-" * 50).green
65
+ puts Rainbow("[INFO] Sending files...#{args}").color(:green)
69
66
  @cases.each { |c| threads << Thread.new { c.send(args) } }
70
67
  threads.each(&:join)
68
+ puts Rainbow("[INFO] Finished").color(:green)
69
+ # puts Rainbow("-" * 50).green
70
+ end
71
+
72
+ def show(options = {verbose: 1})
73
+ verbose = options[:verbose]
74
+ ShowReport.new(@report).call(verbose)
71
75
  end
72
76
  end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: true
1
+ require_relative "hall_of_fame"
2
2
 
3
3
  class CaseManager
4
4
  private
@@ -32,18 +32,16 @@ class CaseManager
32
32
  close_main_report(start_time)
33
33
  end
34
34
 
35
- ##
36
- # Run all cases
37
35
  def run_all_cases
38
36
  start_time = Time.now
37
+ verboseln Rainbow("-" * 36).green
38
+ verboseln Rainbow("Started at #{start_time}").green
39
39
  if Application.instance.global[:tt_sequence] == true
40
- verboseln Rainbow("==> Teuton: Running in sequence (#{start_time})").yellow.bright
41
40
  # Run every case in sequence
42
41
  @cases.each(&:play)
43
42
  else
44
- verboseln Rainbow("==> Teuton: Running in parallel (#{start_time})").yellow.bright
45
- threads = []
46
43
  # Run all cases in parallel
44
+ threads = []
47
45
  @cases.each { |c| threads << Thread.new { c.play } }
48
46
  threads.each(&:join)
49
47
  end
@@ -75,6 +73,6 @@ class CaseManager
75
73
  @cases.each { |c| threads << Thread.new { c.close uniques } }
76
74
  threads.each(&:join)
77
75
 
78
- build_hall_of_fame
76
+ HallOfFame.new(@cases).call
79
77
  end
80
78
  end
@@ -24,7 +24,7 @@ end
24
24
  alias def_macro define_macro
25
25
  alias defmacro define_macro
26
26
 
27
- # Define a group of tests
27
+ # Define a group of [target/run/expect]s
28
28
  # @param name (String) Group name
29
29
  # @param block (Block) Tests code
30
30
  def group(name, &block)
@@ -8,22 +8,22 @@ module ExportManager
8
8
  # @param main_report (Report)
9
9
  # @param cases (Array)
10
10
  # @param input (Hash) Selected export options
11
- def self.run(main_report, cases, input)
12
- args = strings2symbols(input)
11
+ def self.run(main_report, cases, args)
12
+ options = strings2symbols(args)
13
+ if options[:format].nil?
14
+ options[:format] = Application.instance.default[:format]
15
+ end
13
16
 
14
- # default :mode=>:all, :format=>:txt
15
- format = args[:format] || Application.instance.default[:format]
16
- mode = args[:mode] || :all
17
17
  # Step 1: Export case reports
18
- if %i[details all].include? mode
19
- threads = []
20
- cases.each { |c| threads << Thread.new { c.export format } }
21
- threads.each(&:join)
22
- end
18
+ threads = []
19
+ cases.each { |c| threads << Thread.new { c.export(options) } }
20
+ threads.each(&:join)
21
+
23
22
  # Step 2: Export resume report
24
- main_report.export_resume format if %i[resume all].include? mode
23
+ main_report.export_resume(options)
24
+
25
25
  # Step 3: Preserve files if required
26
- preserve_files if args[:preserve] == true
26
+ preserve_files if options[:preserve] == true
27
27
  end
28
28
 
29
29
  ##
@@ -42,7 +42,7 @@ module ExportManager
42
42
  end
43
43
 
44
44
  ##
45
- # Preserve output files for current project
45
+ # Preserve output files for current project execution
46
46
  private_class_method def self.preserve_files
47
47
  app = Application.instance
48
48
  t = Time.now
@@ -55,6 +55,4 @@ module ExportManager
55
55
  FileUtils.mkdir(logdir)
56
56
  Dir.glob(File.join(srcdir, "**.*")).each { |file| FileUtils.cp(file, logdir) }
57
57
  end
58
- # rubocop:enable Metrics/AbcSize
59
- # rubocop:enable Metrics/MethodLength
60
58
  end
@@ -1,26 +1,30 @@
1
1
  require_relative "../application"
2
2
 
3
3
  class CaseManager
4
- private
4
+ class HallOfFame
5
+ def initialize(cases)
6
+ @cases = cases
7
+ end
5
8
 
6
- def build_hall_of_fame
7
- celebrities = {}
9
+ def call
10
+ celebrities = {}
8
11
 
9
- @cases.each do |c|
10
- grade = c.grade # report.tail[:grade]
11
- label = if celebrities[grade]
12
- celebrities[grade] + "*"
13
- else
14
- "*"
12
+ @cases.each do |c|
13
+ grade = c.grade # report.tail[:grade]
14
+ label = if celebrities[grade]
15
+ celebrities[grade] + "*"
16
+ else
17
+ "*"
18
+ end
19
+ celebrities[grade] = label unless c.skip
15
20
  end
16
- celebrities[grade] = label unless c.skip
17
- end
18
21
 
19
- a = celebrities.sort_by { |key, _value| key }
20
- list = a.reverse
22
+ a = celebrities.sort_by { |key, _value| key }
23
+ list = a.reverse
21
24
 
22
- app = Application.instance
23
- app.options[:case_number] = @cases.size
24
- app.hall_of_fame = list
25
+ app = Application.instance
26
+ app.options[:case_number] = @cases.size
27
+ app.hall_of_fame = list
28
+ end
25
29
  end
26
30
  end
@@ -1,4 +1,3 @@
1
1
  require_relative "check_cases"
2
- require_relative "hall_of_fame"
3
2
  require_relative "report"
4
- require_relative "show"
3
+ require_relative "utils"
@@ -25,8 +25,8 @@ class CaseManager
25
25
  @report.tail[:duration] = finish_time - start_time
26
26
 
27
27
  duration = format("%3.3f", (finish_time - start_time))
28
- verbose Rainbow("\n==> Teuton: Duration=#{duration}").yellow.bright
29
- verboseln Rainbow(" (#{finish_time})").yellow.bright
28
+ verboseln Rainbow("\nFinished in #{duration} seconds").green
29
+ verboseln Rainbow("-" * 36).green
30
30
  verboseln " "
31
31
 
32
32
  app = Application.instance
@@ -37,7 +37,7 @@ class CaseManager
37
37
  skip: true,
38
38
  id: "-",
39
39
  grade: 0.0,
40
- letter: "",
40
+ letter: "S",
41
41
  members: "-",
42
42
  conn_status: {},
43
43
  moodle_id: "",
@@ -1,18 +1,17 @@
1
- # frozen_string_literal: true
2
-
3
1
  class BaseFormatter
4
2
  def initialize(report)
5
- @head = report.head
6
- @lines = report.lines
7
- @tail = report.tail
3
+ @head = report.head.clone
4
+ @lines = report.lines.clone
5
+ @tail = report.tail.clone
6
+ @ext = "unkown"
8
7
  end
9
8
 
10
- def process
9
+ def process(options = {})
11
10
  raise "Empty method!"
12
11
  end
13
12
 
14
13
  def init(filename)
15
- @filename = filename
14
+ @filename = "#{filename}.#{@ext}"
16
15
  @file = File.open(@filename, "w")
17
16
  end
18
17
 
@@ -1,6 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base_formatter"
1
+ require_relative "../base_formatter"
2
+ require_relative "../../../application"
4
3
 
5
4
  class ArrayFormatter < BaseFormatter
6
5
  def initialize(report)
@@ -8,26 +7,28 @@ class ArrayFormatter < BaseFormatter
8
7
  @data = {}
9
8
  end
10
9
 
11
- def process
12
- build_data
10
+ def process(options = {})
11
+ build_data(options)
13
12
  w @data.to_s # Write data into ouput file
14
13
  deinit
15
14
  end
16
15
 
17
- def build_data
16
+ def build_data(options)
18
17
  build_initial_data
19
- build_history_data
18
+ build_history_data(options)
20
19
  build_final_data
21
20
  build_hof_data
22
21
  end
23
22
 
23
+ private
24
+
24
25
  def build_initial_data
25
26
  head = {}
26
27
  @head.each { |key, value| head[key] = value }
27
28
  @data[:config] = head
28
29
  end
29
30
 
30
- def build_history_data
31
+ def build_history_data(options)
31
32
  @data[:logs] = []
32
33
  groups = []
33
34
  title = nil
@@ -54,12 +55,22 @@ class ArrayFormatter < BaseFormatter
54
55
  target[:score] = value
55
56
  target[:weight] = i[:weight]
56
57
  target[:description] = i[:description]
57
- target[:command] = i[:command]
58
+
58
59
  target[:conn_type] = i[:conn_type]
59
60
  target[:duration] = i[:duration]
61
+
62
+ target[:command] = i[:command]
60
63
  target[:alterations] = i[:alterations]
61
64
  target[:expected] = i[:expected]
62
65
  target[:result] = i[:result]
66
+
67
+ if options[:feedback] == false
68
+ target[:command] = "*" * i[:command].size
69
+ target[:alterations] = "*" * i[:alterations].size
70
+ target[:expected] = "*" * i[:expected].size
71
+ target[:result] = "*" * i[:result].size
72
+ end
73
+
63
74
  targets << target
64
75
  end
65
76
 
@@ -82,4 +93,28 @@ class ArrayFormatter < BaseFormatter
82
93
  app.hall_of_fame.each { |line| fame[line[0]] = line[1] }
83
94
  @data[:hall_of_fame] = fame
84
95
  end
96
+
97
+ def config
98
+ @data[:config]
99
+ end
100
+
101
+ def results
102
+ @data[:results]
103
+ end
104
+
105
+ def logs
106
+ @data[:logs]
107
+ end
108
+
109
+ def groups
110
+ @data[:groups]
111
+ end
112
+
113
+ def hall_of_fame
114
+ @data[:hall_of_fame]
115
+ end
116
+
117
+ def version
118
+ Application::VERSION
119
+ end
85
120
  end
@@ -0,0 +1,7 @@
1
+ require_relative "txt"
2
+
3
+ class ColoredTextFormatter < TXTFormatter
4
+ def initialize(report)
5
+ super(report, true)
6
+ end
7
+ end