testability-driver-runner 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/bin/sierra +19 -0
  2. data/bin/tdrunner +17 -0
  3. data/lib/tdrunner.rb +208 -0
  4. data/lib/tdrunner.yml +1 -0
  5. data/lib/tdrunner_cucumber.rb +222 -0
  6. data/lib/tdrunner_cucumber_runners.rb +35 -0
  7. data/lib/tdrunner_file_finder.rb +45 -0
  8. data/lib/tdrunner_monitor.rb +473 -0
  9. data/lib/tdrunner_profile.rb +416 -0
  10. data/lib/tdrunner_test_unit.rb +433 -0
  11. data/rakefile +135 -0
  12. data/readme +186 -0
  13. data/websi/README +243 -0
  14. data/websi/Rakefile +10 -0
  15. data/websi/app/controllers/application_controller.rb +29 -0
  16. data/websi/app/controllers/report_editor/test_run/cases_controller.rb +307 -0
  17. data/websi/app/controllers/report_editor_controller.rb +25 -0
  18. data/websi/app/controllers/websi_controller.rb +478 -0
  19. data/websi/app/controllers/websi_script.rb +26 -0
  20. data/websi/app/controllers/websi_support.rb +142 -0
  21. data/websi/app/helpers/application_helper.rb +22 -0
  22. data/websi/app/helpers/report_editor/report_editor_helper.rb +26 -0
  23. data/websi/app/helpers/report_editor/test_run/cases_helper.rb +26 -0
  24. data/websi/app/helpers/websi_helper.rb +21 -0
  25. data/websi/app/views/layouts/application.rhtml +17 -0
  26. data/websi/app/views/websi/execution.html.erb +28 -0
  27. data/websi/app/views/websi/index.html.erb +23 -0
  28. data/websi/app/views/websi/profile.html.erb +30 -0
  29. data/websi/app/views/websi/results.html.erb +30 -0
  30. data/websi/app/views/websi/tests.html.erb +23 -0
  31. data/websi/app/views/websi/weights.html.erb +16 -0
  32. data/websi/config/boot.rb +129 -0
  33. data/websi/config/database.yml +22 -0
  34. data/websi/config/environment.rb +60 -0
  35. data/websi/config/environments/development.rb +36 -0
  36. data/websi/config/environments/production.rb +47 -0
  37. data/websi/config/environments/test.rb +47 -0
  38. data/websi/config/initializers/backtrace_silencers.rb +26 -0
  39. data/websi/config/initializers/inflections.rb +29 -0
  40. data/websi/config/initializers/mime_types.rb +24 -0
  41. data/websi/config/initializers/new_rails_defaults.rb +40 -0
  42. data/websi/config/initializers/session_store.rb +34 -0
  43. data/websi/config/locales/en.yml +5 -0
  44. data/websi/config/routes.rb +62 -0
  45. data/websi/db/development.sqlite3 +0 -0
  46. data/websi/db/seeds.rb +26 -0
  47. data/websi/doc/README_FOR_APP +2 -0
  48. data/websi/log/development.log +0 -0
  49. data/websi/log/production.log +0 -0
  50. data/websi/log/server.log +0 -0
  51. data/websi/log/test.log +0 -0
  52. data/websi/public/report_editor/test_run/_index.html +12 -0
  53. data/websi/public/robots.txt +5 -0
  54. data/websi/public/stylesheets/tdriver_report_style.css +220 -0
  55. data/websi/public/tests/config/web_profile.sip +0 -0
  56. data/websi/public/tests/example_profile.sip +8 -0
  57. data/websi/public/tests/tdrunner.yml +3 -0
  58. data/websi/public/tests/web_profile.sip +8 -0
  59. data/websi/public/tests/websi_parameters.xml +4 -0
  60. data/websi/script/about +4 -0
  61. data/websi/script/console +3 -0
  62. data/websi/script/dbconsole +3 -0
  63. data/websi/script/destroy +3 -0
  64. data/websi/script/generate +3 -0
  65. data/websi/script/performance/benchmarker +3 -0
  66. data/websi/script/performance/profiler +3 -0
  67. data/websi/script/plugin +3 -0
  68. data/websi/script/runner +3 -0
  69. data/websi/script/server +3 -0
  70. data/websi/test/functional/websi_controller_test.rb +27 -0
  71. data/websi/test/performance/browsing_test.rb +28 -0
  72. data/websi/test/test_helper.rb +57 -0
  73. data/websi/test/unit/helpers/websi_helper_test.rb +23 -0
  74. metadata +199 -0
@@ -0,0 +1,26 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ # simple runner script for executing the test unit search in a separate object space
21
+ require 'websi_support.rb'
22
+
23
+ in_path = ARGV[0]
24
+
25
+ locsie = SupportTDRunner::Main.new()
26
+ puts locsie.logtests( in_path )[ 0 ]
@@ -0,0 +1,142 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+
21
+ # Contains modified versions of some tdrunner functionality
22
+ module SupportTDRunner
23
+
24
+ require 'test/unit'
25
+
26
+ class Main
27
+
28
+ def initialize(args = nil)
29
+
30
+ @exclude_folders_pattern = [ '.*', '_*' ]
31
+ @include_files_pattern = [ '*/*.rb' ]
32
+ @tests=nil
33
+ end
34
+
35
+ def features( paths )
36
+
37
+ potential_feature_files = paths.map do |path|
38
+ path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
39
+ path = path.chomp('/')
40
+ if File.directory?(path)
41
+ Dir["#{path}/**/*.feature"]
42
+ elsif path[0..0] == '@' and # @listfile.txt
43
+ File.file?(path[1..-1]) # listfile.txt is a file
44
+ IO.read(path[1..-1]).split
45
+ else
46
+ path
47
+ end
48
+ end.flatten.uniq
49
+ lpt_feature_files = potential_feature_files.sort
50
+ lpt_feature_files
51
+
52
+ end
53
+
54
+ def logtests( value )
55
+
56
+ test_files=[]
57
+ tests=[]
58
+
59
+ # Set to true to prevent autorunning after loading tests
60
+ Test::Unit.run = true
61
+
62
+ test_files.push get_files( value )
63
+
64
+ test_files.each do | test_file |
65
+ tests.push add_file( test_file )
66
+ end
67
+
68
+ return tests
69
+
70
+ end
71
+
72
+ def file_pattern_matches?( patterns, filepath )
73
+ patterns.each{ | pattern | return true if File.fnmatch( pattern, filepath ) }; false
74
+ end
75
+
76
+ def get_files( folder, files_list = [] )
77
+ if File.directory?( folder )
78
+ folder = File.expand_path( folder )
79
+ Dir.open( folder ).each { | entry |
80
+
81
+
82
+ # create full filepath
83
+ filepath = "#{ folder }/#{ entry }"
84
+ # file: add file to required files list
85
+ files_list.push( filepath ) if file_pattern_matches?( @include_files_pattern, filepath )
86
+ # directory: go deeper in folder stack structure if exclusion pattern does not meet
87
+ files_list |= get_files("#{ filepath }/") if File.directory?( filepath ) and not file_pattern_matches?( @exclude_folders_pattern, entry )
88
+
89
+ }
90
+ files_list
91
+ else
92
+ folder
93
+ end
94
+ end
95
+
96
+ def add_file( tests )
97
+ collected_tests_and_classes=[]
98
+ @tests = []
99
+ @testcases = 0
100
+ tests = [ tests ] unless tests.kind_of?( Array )
101
+ tests.each{ | filename |
102
+
103
+ # expand wildcards to array if found
104
+ testsuites = ( filename.include?( '*' ) ? ( ( tmp = Dir.glob( filename ) ).empty? ? [ filename ] : tmp ): [ filename ] )
105
+
106
+ testsuites.each{ | testsuite_filename |
107
+
108
+ if File.exist?( testsuite_filename )
109
+ begin
110
+ require testsuite_filename
111
+ rescue NoMethodError
112
+ end
113
+ else
114
+ Kernel::raise LoadError.new( "Unable to add testcase to suite due to file not found (#{ testsuite_filename })" )
115
+ end
116
+
117
+ }
118
+
119
+ }
120
+
121
+ ObjectSpace.each_object( Class ){ | test_class |
122
+ if test_class.ancestors.include?( Test::Unit::TestCase ) && test_class != Test::Unit::TestCase
123
+ unless @tests.include? test_class
124
+ collected_tests_and_classes << test_class.to_s
125
+ #test_class.public_instance_methods( false ).sort.each{ | method |
126
+ test_class.public_instance_methods( false ).each{ | method |
127
+ if method =~ /^test_/
128
+ collected_tests_and_classes << method+"(#{test_class})"
129
+ @testcases += 1
130
+ end
131
+ }
132
+ @tests.push test_class
133
+ end
134
+ end
135
+ }
136
+
137
+ return collected_tests_and_classes
138
+ end
139
+
140
+ end
141
+
142
+ end
@@ -0,0 +1,22 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ # Methods added to this helper will be available to all templates in the application.
21
+ module ApplicationHelper
22
+ end
@@ -0,0 +1,26 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ require 'nokogiri'
21
+ module ReportEditor::ReportEditorHelper
22
+
23
+
24
+
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ require 'nokogiri'
21
+ module ReportEditor::TestRun::CasesHelper
22
+
23
+
24
+
25
+
26
+ end
@@ -0,0 +1,21 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ module WebsiHelper
21
+ end
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html;.
6
+ charset=iso-8859-1" />
7
+ <meta http-equiv="Content-Language" content="en-us" />
8
+ <%= stylesheet_link_tag "tdriver_report_style" %>
9
+ </head>
10
+ <body id="library">
11
+
12
+ <div id="content">
13
+ <%= yield -%>
14
+ </div>
15
+
16
+ </body>
17
+ </html>
@@ -0,0 +1,28 @@
1
+ Progress: <%= link_to "Start", "index" %> -> <%= link_to "Tests", "tests" %> -> <%= link_to "Weights", "weights" %> -> <%= link_to "Profile", "profile" %> -> <b>Execute</b> -> Results<br>
2
+ <h1>Review and start test execution</h1>
3
+ <%= session[ :exec_friendly ] %><br>
4
+ The following weights will be used. You may also save the test profile for later use before executing it. Saved profiles can be loaded from the websi start page.
5
+ <%= form_tag :action => "after_execution" %>
6
+ <br>Test weights:<br>
7
+ <% test_keys = session[ :test_keys ] %>
8
+ <% test_keys.each do | key_test | %>
9
+ <% test_weight = @exec_tests.fetch(key_test, "0") %>
10
+ <% if test_weight.to_i > 0 %>
11
+ <%= key_test + " = " + test_weight.to_s %><br>
12
+ <% end %>
13
+ <% end %>
14
+ <br>
15
+ <% if session[ :ordered_enable ] == true %>
16
+ Tests will be executed in the order they appear above.<br>
17
+ <% end %>
18
+ <% if session[ :teardown_enable ] == true %>
19
+ Teardown for Test::Unit tests will only be executed when a test case fails.<br>
20
+ <% end %>
21
+ <%= submit_tag "Execute", :name => "submit" %>
22
+ <p>
23
+ <br>Profile name: <%= text_field_tag "save_as_name", session[ :loaded_profile_name ] %>
24
+ <%= submit_tag "Save", :name => "submit" %>
25
+ <% if @save_message.kind_of? String and !@save_message.empty? %>
26
+ <b><%= @save_message %></b>
27
+ <% end %>
28
+ </form>
@@ -0,0 +1,23 @@
1
+ Progress: <b>Start</b> -> Tests -> Weights -> Profile -> Execute -> Results<br>
2
+ <h1>websi - TDRunner web interface</h1>
3
+ You can use TDRunner with an existing test set profile or create a new one. Available profiles are listed in the drop down box.
4
+ <%= form_tag :action => "after_index" %>
5
+ <%= submit_tag "Create new profile" %>
6
+ </form>
7
+ <p>
8
+ <%= form_tag :action => "load_profile" %>
9
+ Use existing profile:<br>
10
+ <% prof_listing = @existing_profiles.map{ | prof_name | "<option>#{prof_name}</option>" }.to_s %>
11
+ <%= select_tag "prof_name", prof_listing %><br>
12
+ <%= submit_tag "Use this profile" %>
13
+ </form>
14
+ <% if session[ :index_message ].kind_of? String and !session[ :index_message ].empty? %>
15
+ <b><%= session[ :index_message ] %></b>
16
+ <% end %>
17
+ <br><br>
18
+ Test run history:<br>
19
+ <% ii = 1 %>
20
+ <% @index_files.each do | ifile | %>
21
+ <%= link_to "Test run " + ii.to_s + ": " + ifile , "/tests/reports/test_run_" + ifile + "/index.html" %><br>
22
+ <% ii = ii + 1 %>
23
+ <% end %>
@@ -0,0 +1,30 @@
1
+ Progress: <%= link_to "Start", "index" %> -> <%= link_to "Tests", "tests" %> -> <%= link_to "Weights", "weights" %> -> <b>Profile</b> -> Execute -> Results<br>
2
+ <h1>Set TDRunner execution options</h1>
3
+ <%= form_tag :action => "after_profile" %>
4
+
5
+ Choose whether to execute your test set for a defined number of iterations or for a set time.
6
+ <br>
7
+ <% type_descriptions = {
8
+ 'Iterations' => 'Iterations. Your test set profile will executed this many times',
9
+ 'Elapsed' => 'Elapsed hours. Execution will continue for this many hours',
10
+ 'Timestamp' => 'Timestamp, "DD.MM.YYYY HH:MM". Execution will continue until the defined timestamp is reached'
11
+ } %>
12
+ <% now_string = DateTime.now.to_s
13
+ now_string = now_string[8,2] + "." + now_string[5,2] + "." + now_string[0,4] + " " + now_string[11,2] + ":" + now_string[14,2]
14
+ type_defaults = {
15
+ 'Iterations' => (@loaded_amount == "" || @exec_type != "Iterations")? "1" : session[ :loaded_amount ],
16
+ 'Elapsed' => (@loaded_amount == "" || @exec_type != "Elapsed" )? "1" : session[ :loaded_amount ],
17
+ 'Timestamp' => (@loaded_amount == "" || @exec_type != "Timestamp" )? now_string : session[ :loaded_amount ]
18
+ } %>
19
+ <% @exec_type = "Iterations" if @exec_type.nil? or @exec_type == "" %>
20
+ <% [ 'Iterations', 'Elapsed', 'Timestamp' ].each do | exec_type | %>
21
+ <br><%= radio_button_tag 'exec_type', exec_type, @exec_type == exec_type %>
22
+ <%= text_field_tag "text_" + exec_type, type_defaults[ exec_type ] %> <%= type_descriptions[ exec_type ] %>
23
+ <% end %>
24
+ <p>
25
+ Execution options:
26
+ <br><%= check_box_tag 'teardown_enable', 'true', ( session[ :teardown_enable ] == true ) %> Teardown for Test::Unit tests is only executed when a test case fails.
27
+ <br><%= check_box_tag 'ordered_enable', 'true', ( session[ :ordered_enable ] == true ) %> Tests are executed in the order they appear in the sip file.
28
+ <p>
29
+ <%= submit_tag "Use these options" %>
30
+ </form>
@@ -0,0 +1,30 @@
1
+ Progress: <%= link_to "Start", "index" %> -> <%= link_to "Tests", "tests" %> -> <%= link_to "Weights", "weights" %> -> <%= link_to "Profile", "profile" %> -> <%= link_to "Execute", "execution" %> -> <b>Results</b><br>
2
+
3
+ <h1>Test results</h1>
4
+
5
+ Test set execution started at <%= session[ :start_time ] %>.<br>
6
+ <%= session[ :exec_friendly ] %><br>
7
+ <br>Test weights:<br>
8
+ <% test_keys = session[ :test_keys ] %>
9
+ <% test_keys.each do | key_test | %>
10
+ <% test_weight = session[:weights].fetch(key_test, "0") %>
11
+ <% if test_weight.to_i > 0 %>
12
+ <%= key_test + " = " + test_weight.to_s %><br>
13
+ <% end %>
14
+ <% end %>
15
+ <br>
16
+ <br>
17
+ <% if @new_reports.empty? %>
18
+ Test run starting... please wait and refresh.
19
+ <% else %>
20
+ Test run summary:<br><br>
21
+ <div id="container">
22
+ <iframe src="<%= "/tests/reports/test_run_" + @new_reports[-1] + "/index.html" %>" scrolling="no" ></iframe>
23
+ </div>
24
+ <br>View full report: <%= link_to "Test run " + @new_reports[-1] , "/tests/reports/test_run_" + @new_reports[-1] + "/index.html" %>
25
+ <% end %>
26
+
27
+ <br><br>
28
+ <%= form_tag :action => "results" %>
29
+ <%= submit_tag "Refresh", :name => "submit" %> <!-- <%= submit_tag "Pause", :name => "submit" %> <%= submit_tag "Stop", :name => "submit" %> -->
30
+ </form>
@@ -0,0 +1,23 @@
1
+ Progress: <%= link_to "Start", "index" %> -> <b>Tests</b> -> Weights -> Profile -> Execute -> Results<br>
2
+ <h1>Select tests</h1>
3
+ Select test root folder and tests to be executed
4
+ <%= form_tag :action => "tests" %>
5
+
6
+ Enter test folder:
7
+ <%= text_field_tag "test_path", @test_path.to_s %>
8
+ <%= submit_tag "Load tests from folder" %><%= check_box_tag 'load_tc', 'true', ( session[ :load_tc ] == true ) %> Load Test::Unit test classes in addition to tests.<br>
9
+
10
+ </form>
11
+ <% if !@test_names.nil? && !@test_names.empty? %>
12
+ <%= 'Test folder: ' + @test_path.to_s %><br>
13
+ Select any tests you wish to execute
14
+ <% test_listing = @test_names.map{ | test_name | "<option>#{test_name}</option>" }.to_s %>
15
+ <%= form_tag :action => "after_tests" %>
16
+ <%= select_tag "selected_tests[]", test_listing, :multiple => true %>
17
+ <br><%= submit_tag "Select" %>
18
+ <%= '</form>' %>
19
+ <% end %>
20
+ <% if session[ :tests_message ].kind_of? String and !session[ :tests_message ].empty? %>
21
+ <b><%= session[ :tests_message ] %></b>
22
+ <% end %>
23
+
@@ -0,0 +1,16 @@
1
+ Progress: <%= link_to "Start", "index" %> -> <%= link_to "Tests", "tests" %> -> <b>Weights</b> -> Profile -> Execute -> Results<br>
2
+ <h1>Set test weights</h1>
3
+ <%= form_tag :action => "after_weights" %>
4
+ <% @profile_tests = session[ :weights ] if @profile_tests.nil? or @profile_tests.empty? %>
5
+ Set relative weights for your tests based on their importance. The weight of a test will directly affect how many times it will be executed compared to a test with a weight of 1.
6
+ <br>
7
+ <% test_keys = session[ :test_keys ] %>
8
+ <% test_keys.each do | key_test | %>
9
+ <% test_weight = @profile_tests.fetch( key_test, "0" ) %>
10
+ <%= text_field_tag "weights[#{key_test}]", test_weight.empty? ? "0" : test_weight.to_s , :class => "test-weight" %>
11
+ <%= key_test.to_s %>
12
+ <br>
13
+ <% end %>
14
+ <%= submit_tag "Set weights" %>
15
+
16
+ </form>