robotest 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,207 @@
1
+ # RoboTest
2
+
3
+ Robotest is a Page Object Model (POM) framework for selenium automation with ruby 'rspec'. In order to make the testing faster, robotest included the 'parallel_tests' gem to make multiple process testing at the same time. For reporting 'allure' is being adapted.
4
+
5
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)
6
+ [![Made with Ruby](https://img.shields.io/badge/Made%20with-Ruby-red.svg)](https://www.ruby-lang.org/en/)
7
+ [![Gitter](https://img.shields.io/badge/Gitter-Chat-green.svg)](https://gitter.im/POM-selenium-framework/POM-Selenium-rspec-framework)
8
+ [![StackOverflow](http://img.shields.io/badge/Stack%20Overflow-Ask-blue.svg)]( https://stackoverflow.com/users/10505289/naresh-sekar )
9
+ [![Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](CONTRIBUTING.md)
10
+ [![email me](https://img.shields.io/badge/Contact-Email-green.svg)](nareshnavinash@gmail.com)
11
+
12
+ ![alt text](lib/robotest/RoboTest.png)
13
+
14
+ ## Getting Started
15
+
16
+ For faster onboarding sample project has been added to this gem. Just try
17
+
18
+ ```
19
+ robotest example
20
+ ```
21
+ to get a sample project loaded in to your current directry.
22
+
23
+ Note: This will work for linux and mac machines. For windows machines try to copy paste the sample project folder `Full_Suite` from the installation directory.
24
+
25
+
26
+ ### Prerequisites
27
+
28
+ * Install Sublime, Atom, Code or Xcode based on your preference
29
+ * Install homebrew from http://brew.sh/
30
+ * Install ruby and rvm with `brew install ruby` and `curl -sSL https://get.rvm.io | bash -s stable --ruby`
31
+ * Install chrome driver using `brew cask install chromedriver`
32
+
33
+ Note: The above all is for linux and mac machines. For windows machines the installation may vary.
34
+
35
+
36
+ ### Installing
37
+
38
+ Install using `gem install` command
39
+
40
+ ```
41
+ gem install robotest
42
+ ```
43
+
44
+ or
45
+
46
+ 1. Clone this project to your local.
47
+ 2. Inside the cloned project directory do `bash build.sh`
48
+
49
+
50
+ ## Running the tests
51
+
52
+ At first you need to describe your tests in the spec folder with .rb extention. Then need to add your spec file directory in the yaml file as given in the example file. Now run the tests with the following command
53
+
54
+ ```
55
+ robotest <Directory to your yaml file>
56
+ ```
57
+ In the example project you can try
58
+ ```
59
+ robotest yaml/test.yml
60
+ ```
61
+ in the directory where the example project is placed.
62
+
63
+ To run the tests in parallel mode using `parallel_tests` try running
64
+ ```
65
+ robotest yaml/test_parallel.yml
66
+ ```
67
+ in the directory where the example project is placed.
68
+
69
+
70
+ ### Break down into end to end tests
71
+
72
+ **Adding Locators to the project**
73
+
74
+ 1. Add Locators to the that are going to be used inside the project inside the `Locators` module
75
+ ```
76
+ module Locators
77
+ # Add a class for each page and add the locators
78
+ end
79
+ ```
80
+ 2. For each page add a new class inside the `Locators` module.
81
+ ```
82
+ module Locators
83
+ class TestPage
84
+
85
+ # All the Locators in the initialize block need to be declared here for read write permission.
86
+ attr_accessor :TEST_LOCATOR
87
+
88
+ def initialize
89
+ # Locators can be declared here by mentioning {how?(xpath,css,id) and what?(identifier)}
90
+ @TEST_LOCATOR = Locator.new(:id, "")
91
+ end
92
+
93
+ # Dynamic locators can be declared here as a seperate method (This method doesnot need to be declared with attr_accessor)
94
+ def TEST_DYNAMIC_LOCATOR(variable)
95
+ @TEST_DYNAMIC_LOCATOR = Locator.new(:xpath,"//*[text()=#{variable}]")
96
+ end
97
+
98
+ end
99
+ end
100
+ ```
101
+ 3. Ideally each web page should have a new file inside locators folder (with the same name as the web page) and all the locators inside a web page has to be declared inside a page class(Class name also should be same as the web page name).
102
+ * If the web page name is `home page` then the locator file name should be `home_page.rb` inside `locators` folder and the class name should be `HomePage` inside `Locators` module.
103
+
104
+ **Adding page methods to the project**
105
+
106
+ 1. Add page specific methods inside the `Pages` module.
107
+ ```
108
+ module Pages
109
+ # add the page class here
110
+ end
111
+ ```
112
+ 2. For each page add a new class inside `Pages` module and each page class should inherit the locators class of the same page..
113
+ ```
114
+ module Pages
115
+ class TestPage < Locators::TestPage
116
+
117
+ def initialize(driver)
118
+ super()
119
+ @driver = driver
120
+ end
121
+
122
+ def test_method(attribute_text)
123
+ puts "#{attribute_text}"
124
+ end
125
+
126
+ end
127
+ end
128
+ ```
129
+ 3. Ideally each web page should have a new page file inside `pages` folder with the class name same as the web page name.
130
+ * If the web page name is `home page` then the pages file name should be `home_page.rb` inside `pages` folder and the class name should be `HomePage` inside `Pages` module.
131
+
132
+ **Creating a new spec file in the project**
133
+
134
+ 1. Require the spec_helper file.
135
+ ```
136
+ require 'spec_helper'
137
+ ```
138
+ 2. Describe the test case with a unique name.
139
+ ```
140
+ describe "Testing" do
141
+
142
+ end
143
+ ```
144
+ 3. Declare the before all, before each, after all, after each if needed inside the describe. *check out the spec_helper file to have a global before and after blocks*
145
+ ```
146
+ before(:all) do
147
+ # Initialize all the constants here.
148
+ # Code which has to be run before starting all the test cases are placed here.
149
+ end
150
+
151
+ before(:each) do
152
+ # any specfic steps that needs to be done before each testcase can be done here
153
+ # Example : Moving to the home page after all the test case will be an idle one.
154
+ end
155
+
156
+ after(:all) do
157
+ # Steps that is to be run after all the test cases are done can be given here.
158
+ # Usual steps will be quiting all the drivers, but that is handled in the spec_helper.rb so any other specific steps other than quit can be given here.
159
+ end
160
+
161
+ after(:each) do |e|
162
+ # any specfic steps that needs to be done after each testcase can be done here
163
+ # Usually taking screen shots after each test case when there is a failure is done here, but that is covered in spec_helper.rb
164
+ # Any other steps than taking screenshot can be given here.
165
+ end
166
+ ```
167
+ 4. Now declare your tests after the before and after block within the descibe block.
168
+ ```
169
+ it 'Test 1',:tag_string => "tag_name", :tag_boolean => true, :tag_number => '001' do |e|
170
+ #use e.step to have the reporting in the allure.
171
+ e.step "test reporting 1" do
172
+ expect(true).to eql true
173
+ end
174
+ # Best practice is to have more e.step and have all the code inside any of the e.step so that any failure happend in the test case will be reported with screenshots.
175
+ end
176
+ ```
177
+ *For more check the sample files after doing `robotest example`*
178
+
179
+
180
+ ## Built With
181
+
182
+ * [Rspec](https://rubygems.org/gems/rspec/versions/3.4.0) - Automation core framework
183
+ * [Parallel_tests](https://rubygems.org/gems/parallel_tests) - To run automation parallely at the same time.
184
+ * [Allure Rspec](https://rubygems.org/gems/allure-rspec) - For Detailed reporting.
185
+ * [Selenium](https://www.seleniumhq.org/) - For web browser automation.
186
+
187
+ ## Contributing
188
+
189
+ 1. Fork it!
190
+ 2. Create your feature branch: `git checkout -b my-new-feature`
191
+ 3. Commit your changes: `git commit -am 'Add some feature'`
192
+ 4. Push to the branch: `git push origin my-new-feature`
193
+ 5. Submit a pull request :D
194
+
195
+ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on code of conduct, and the process for submitting pull requests.
196
+
197
+ ## Authors
198
+
199
+ * **[Naresh Sekar](https://github.com/nareshnavinash)**
200
+
201
+ ## License
202
+
203
+ This project is licensed under the GNU GPL-3.0 License - see the [LICENSE](LICENSE) file for details
204
+
205
+ ## Acknowledgments
206
+
207
+ * To all the open source contributors whose code has been used in this project.
@@ -0,0 +1 @@
1
+ import "./lib/tasks/robotest.rake"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'robotest'
4
+
5
+ RoboTest::CLI.new.invoke(ARGV)
@@ -0,0 +1,258 @@
1
+ require 'selenium-webdriver'
2
+ require 'yaml'
3
+ require 'yaml_extend'
4
+ require 'rspec/core'
5
+ require 'parallel_tests'
6
+ require 'optparse'
7
+ require 'pry'
8
+ require 'progress_bar'
9
+ require 'readline'
10
+ require_relative "./robotest/driver.rb"
11
+ require_relative "./robotest/locator.rb"
12
+ require_relative "./robotest/version.rb"
13
+ require_relative "./robotest/wait.rb"
14
+ require_relative "./robotest/dsl.rb"
15
+ require_relative "./robotest/multilocator.rb"
16
+
17
+ module RoboTest
18
+
19
+ class CLI
20
+
21
+ $conf
22
+ def invoke(argv)
23
+ `gem cleanup`
24
+ logo
25
+ welcome_message
26
+ if argv.empty?
27
+ help_text
28
+ puts "Add a path to an yaml file to start running your suite\n"
29
+ puts "Enter a path to your yaml file:\n"
30
+ argv = STDIN.gets
31
+ if !argv.include? ".yml"
32
+ puts "Need to enter the path for a configured yml file !!!"
33
+ exit_message
34
+ exit!
35
+ end
36
+ end
37
+ at_exit {
38
+ delete_temp_files
39
+ }
40
+ example if argv.include?('example')
41
+ options, rspec_args = parse_options(argv)
42
+ $conf = load_config_file(argv[0], options)
43
+ modified_argv = setup_args(argv, $conf, rspec_args)
44
+ yaml_dump('_robotest.yml', $conf)
45
+ run(modified_argv)
46
+ end
47
+
48
+ private
49
+
50
+ def opt_parser_banner
51
+ puts "RoboTest is built over rspec, parallel_tests and allure.\n\n"
52
+ help_text
53
+ puts "1. Install Sublime, Atom, Code or Xcode based on your preference\n"
54
+ puts "2. Install homebrew from http://brew.sh/\n"
55
+ puts "3. Install ruby and rvm with `brew install ruby` and `curl -sSL https://get.rvm.io | bash -s stable --ruby`\n"
56
+ puts "4. Install chrome driver using `brew cask install chromedriver`\n"
57
+ puts "5. For sample project run `robotest example` and move to that directory in the command prompt\n"
58
+ puts "6. Now Make sure to rename the project name from `Full_Suite` to your `Custom Name`\n"
59
+ puts "7. Rename the file `rspec_parallel` in Full_Suite/ folder to `.rspec_parallel` to get the console logs while running the scripts !!!\n"
60
+ puts "8. To test a sample run with single process try running `robotest yaml/test.yml`\n"
61
+ puts "9. To test a sample run with multiple process try running `robotest yaml/test_parallel.yml`\n"
62
+ puts "10. You can specify the additional parameters as follows,\n> robotest yaml/test.yml -t sanity||true\n"
63
+ puts "Here test cases with sanity tag alone will run \n\n
64
+ Other additional parameters are:"
65
+ end
66
+
67
+ def exit_message
68
+ puts "\nExiting ...!!!"
69
+ end
70
+
71
+ def logo
72
+ puts "
73
+ _______________________________________________________________________________________________
74
+ RRRRRRRRR OOOOOOOOOO BBBBBBBBB OOOOOOOOOO TTTTTTTTTTT EEEEEEEEE SSSSSSSS TTTTTTTTTTT
75
+ R r O O B b O O T E S T
76
+ R R O O B B O O T E S T
77
+ R r O O B b O O T E S T
78
+ RRRRRRRRR O O BBBBBBBBB O O T EEEEEEEEE SSSSSSSS T
79
+ R R O O B b O O T E S T
80
+ R R O O B B O O T E S T
81
+ R R O O B b O O T E S T
82
+ R r OOOOOOOOOO BBBBBBBBB OOOOOOOOOO T EEEEEEEEE SSSSSSSS T
83
+ -----------------------------------------------------------------------------------------------
84
+ "
85
+ end
86
+
87
+ def welcome_message
88
+ puts "Welcome to RoboTest !!!\n\n"
89
+ end
90
+
91
+ def help_text
92
+ puts "New to RoboTest? try \n> robotest example \nto get a sample project get loaded in your directory \n \n"
93
+ puts "Need help in running the suite? try \n> robotest -h\nfor help (or) \n \n"
94
+ end
95
+
96
+ def example
97
+ begin
98
+ source_directory = File.dirname(__FILE__) + "/../Full_Suite/."
99
+ destination_directory = Dir.pwd + "/Full_Suite/"
100
+ `cp -a #{source_directory} #{destination_directory}`
101
+ puts "\n\nInitialized sample robotest project in #{destination_directory}\n\n"
102
+ puts "Follow the following steps to make sure everyting is setup in a right way:"
103
+ puts "1. Now Make sure to rename the project name from `Full_Suite` to your `Custom Name`"
104
+ puts "2. Rename the file `rspec_parallel` in Full_Suite/ folder to `.rspec_parallel`. Navigate to your project and Do `bundle install` before proceeding with the following step"
105
+ puts "3. To test a sample run with single process try running `robotest yaml/test.yml`"
106
+ puts "4. To test a sample run with multiple process try running `robotest yaml/test_parallel.yml`\n\n"
107
+ exit_message
108
+ exit!
109
+ rescue Exception => e
110
+ puts e.message
111
+ puts e.backtrace
112
+ ensure
113
+ exit_message
114
+ exit!
115
+ end
116
+ end
117
+
118
+ def generate(argv)
119
+ begin
120
+ raise 'Pass module name as an argument, example: robotest generate login' unless argv.length >= 2
121
+ argv.each do |file_name|
122
+ next if file_name == 'generate'
123
+ class_name = file_name.split('_').collect(&:capitalize).join
124
+ locators_file_path = File.read(File.join(File.dirname(__FILE__), '..', 'templates', 'locators.erb'))
125
+ pages_file_path = File.read(File.join(File.dirname(__FILE__), '..', 'templates', 'pages.erb'))
126
+ File.write(File.join(Dir.pwd, 'locators', "#{file_name}.rb"), ERB.new(locators_file_path).result(binding))
127
+ File.write(File.join(Dir.pwd, 'pages', "#{file_name}.rb"), ERB.new(pages_file_path).result(binding))
128
+ puts "Template class: '#{class_name}' is created under pages and locators directory"
129
+ end
130
+ rescue Exception => e
131
+ puts e.message
132
+ puts e.backtrace
133
+ ensure
134
+ exit_message
135
+ exit!
136
+ end
137
+ end
138
+
139
+ def run(argv)
140
+ if $conf["mode"] == 'parallel'
141
+ ParallelTests::CLI.new.run(["--type", "rspec"] + argv)
142
+ else
143
+ ParallelTests::CLI.new.run(["--type", "rspec", "--first-is-1", "-n", "1"] + argv)
144
+ end
145
+ end
146
+
147
+ def yaml_dump(filename, data)
148
+ File.open(filename, 'w') do |f|
149
+ f.write(YAML.dump(data))
150
+ end
151
+ end
152
+
153
+ def delete_temp_files
154
+ File.delete('_robotest.yml') if File.exist?('_robotest.yml')
155
+ end
156
+
157
+ def setup_args(argv, conf, rspec_args)
158
+ argv.shift
159
+ conf["specs"].each { |spec| argv << spec } if argv.empty?
160
+ argv.unshift('--')
161
+ if conf["tag"]
162
+ if conf["tag"].class == Hash
163
+ conf["tag"].each do|key, value|
164
+ argv.unshift("#{key}:#{value}")
165
+ argv.unshift("-t")
166
+ end
167
+ else
168
+ tags = conf["tag"].split("&&")
169
+ tags.each do|tag|
170
+ argv.unshift(tag)
171
+ argv.unshift("-t")
172
+ end
173
+ end
174
+ end
175
+ argv.unshift(conf['exclude'].join(',')) unless conf['exclude'].nil?
176
+ argv.unshift('--exclude-pattern') unless conf['exclude'].nil?
177
+ argv.unshift('--only-failures') if conf['only_failures']
178
+ argv.unshift('@sanity:true') if conf['sanity']
179
+ argv.unshift('--tag') if conf['sanity']
180
+ argv.unshift('--')
181
+ argv.unshift('--first-is-1')
182
+ if conf['mode'] == 'parallel' and conf['count']
183
+ argv.unshift(conf['count'])
184
+ argv.unshift('-n')
185
+ end
186
+ return argv
187
+ end
188
+
189
+ def load_config_file(file, options)
190
+ raise "An yaml file needs to be" if !File.file?(file)
191
+ configFile = YAML.ext_load_file(file)
192
+ configFile["base_urls"] = options[:url].split(',') if options[:url]
193
+ configFile["browser"] = options[:browser] if options[:browser]
194
+ configFile["remote"] = options[:remote] if options[:remote]
195
+ if configFile["parallel_process"] != nil
196
+ configFile["count"] = "#{configFile["parallel_process"]}"
197
+ else
198
+ configFile["count"] = options[:count] ? options[:count] : configFile["base_urls"].length.to_s
199
+ end
200
+ configFile["mode"] = options[:mode] if options[:mode]
201
+ configFile["only_failures"] = options[:only_failures] if options[:only_failures]
202
+ configFile["tag"] = options[:tag] if options[:tag]
203
+ configFile["dimensions"]["horizontal"] = options[:horizontal] if options[:horizontal]
204
+ configFile["dimensions"]["vertical"] = options[:vertical] if options[:vertical]
205
+ configFile["testrail"]["run_id"] = options[:runid].to_i if options[:runid]
206
+ configFile["buildURL"] = options[:buildURL] if options[:buildURL]
207
+ configFile
208
+ end
209
+
210
+ def parse_options(argv)
211
+
212
+ options = {}
213
+ rspec_args = []
214
+
215
+ OptionParser.new do |opts|
216
+ opts.banner = <<-BANNER.gsub(/^ /, '')
217
+ BANNER
218
+
219
+ opts.on("-f", "--format FORMATTER", "Result format as specified in rspec") do |format|
220
+ options[:format] = format
221
+ rspec_args << '-f' << format
222
+ end
223
+
224
+ opts.on("-t", "--tag TAG[:VALUE]", "Run examples with the specified tag") do |tag|
225
+ options[:tag] = tag
226
+ rspec_args << '-t' << tag
227
+ end
228
+
229
+ opts.on("-e", "--example STRING", "Runs test cases with the specified string") do |example|
230
+ options[:example] = example
231
+ rspec_args << '-e' << example
232
+ end
233
+
234
+ opts.on("", "--only-failures", "Run only the failures from the last run") do |only_failures|
235
+ options[:only_failures] = only_failures
236
+ rspec_args << '--only-failures'
237
+ end
238
+
239
+ opts.on("-n", "--count COUNT", "Process count.") { |count| options[:count] = count }
240
+ opts.on("-u", "--url URL", "Run scripts with this url.") { |url| options[:url] = url }
241
+ opts.on("-x", "--horizontal HORIZONTAL", "Browser dimension in horizontal direction") { |horizontal| options[:horizontal] = horizontal.to_i }
242
+ opts.on("-y", "--vertical VERTICAL", "Browser dimension in vertical direction") { |vertical| options[:vertical] = vertical.to_i }
243
+ opts.on("-b", "--browser BROWSER", "chrome/firefox/edge/safari") { |browser| options[:browser] = browser }
244
+ opts.on("-m", "--mode MODE", "single/parallel") { |mode| options[:mode] = mode }
245
+ opts.on("-v", "--version", "Show version.") { puts "Version - #{RoboTest::VERSION}\n"; exit 0 }
246
+ opts.on("-h", "--help", "Print help.") {
247
+ opt_parser_banner
248
+ puts opts;
249
+ exit_message
250
+ exit! }
251
+ end.parse!
252
+
253
+ [options, rspec_args]
254
+
255
+ end
256
+
257
+ end
258
+ end