teber-library 0.1.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/README.md +8 -0
  4. data/exe/teber +5 -0
  5. data/lib/teber.rb +38 -2
  6. data/lib/teber/version.rb +1 -1
  7. data/sample/.DS_Store +0 -0
  8. data/sample/.gitignore +1 -0
  9. data/sample/CONTRIBUTING.md +93 -0
  10. data/sample/Gemfile +20 -0
  11. data/sample/Gemfile.lock +130 -0
  12. data/sample/LICENSE +674 -0
  13. data/sample/README.md +263 -0
  14. data/sample/_config.yml +1 -0
  15. data/sample/config/cucumber.yml +2 -0
  16. data/sample/features/.DS_Store +0 -0
  17. data/sample/features/feature/.gitkeep +0 -0
  18. data/sample/features/feature/googleSearch.feature +27 -0
  19. data/sample/features/feature/googleSearchParallel.feature +9 -0
  20. data/sample/features/global-data/.gitkeep +0 -0
  21. data/sample/features/global-data/global.yml +4 -0
  22. data/sample/features/libraries/.gitkeep +0 -0
  23. data/sample/features/libraries/Teber_Ruby_Black.png +0 -0
  24. data/sample/features/libraries/categories.json +31 -0
  25. data/sample/features/libraries/driver.rb +212 -0
  26. data/sample/features/libraries/locator.rb +146 -0
  27. data/sample/features/libraries/wait.rb +31 -0
  28. data/sample/features/locators/.gitkeep +0 -0
  29. data/sample/features/locators/googleSearch.rb +18 -0
  30. data/sample/features/pages/.gitkeep +0 -0
  31. data/sample/features/pages/googleSearch.rb +21 -0
  32. data/sample/features/step_definitions/.gitkeep +0 -0
  33. data/sample/features/step_definitions/googleSearch.rb +31 -0
  34. data/sample/features/support/env.rb +82 -0
  35. data/sample/features/test-data/.gitkeep +0 -0
  36. data/sample/features/test-data/googleSearch.yml +2 -0
  37. data/sample/features/test-data/googleSearchParallel.yml +2 -0
  38. data/teber-library.gemspec +12 -0
  39. metadata +202 -2
data/sample/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # Teber-Ruby
2
+
3
+ Teber-Ruby is a Page Object Model (POM) framework for selenium automation with ruby `Cucumber`. In order to make the testing faster used 'parallel_tests' gem to run multiple threads to run the tests 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
+ [![StackOverflow](http://img.shields.io/badge/Stack%20Overflow-Ask-blue.svg)]( https://stackoverflow.com/users/10505289/naresh-sekar )
8
+ [![Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](CONTRIBUTING.md)
9
+ [![email me](https://img.shields.io/badge/Contact-Email-green.svg)](nareshnavinash@gmail.com)
10
+
11
+
12
+ ![alt text](features/libraries/Teber_Ruby_Black.png)
13
+
14
+
15
+ ## Supports
16
+ * Multiple browser automation
17
+ * Multi browser automation
18
+ * Allure reports
19
+ * Jenkins Integration
20
+ * Modes of run via CLI command
21
+ * Headless run
22
+ * Docker Execution
23
+ * Failed Screenshots
24
+ * Testdata driven tests
25
+ * Multi Thread run
26
+
27
+ ## Setup
28
+ * Clone this repository
29
+ * Navigate to the cloned folder
30
+ * Install bundler using `gem install bundler`
31
+ * Install the dependencies by `bundle install`
32
+
33
+ ## To Run the tests
34
+ For a simple run of all the feature files in normal mode, try
35
+ ```
36
+ cucumber
37
+ ```
38
+ To Run the tests in parallel mode for the available feature files, try
39
+
40
+ ```
41
+ parallel_cucumber features/
42
+ ```
43
+ To Run the tests in parallel mode for the available feature files along with tags, try
44
+ ```
45
+ parallel_cucumber features/ -o "-t "@scenario_001""
46
+ ```
47
+ To Run the tests in parallel mode for the available feature files along with tags and environment variables, try
48
+ ```
49
+ parallel_cucumber features/ -o "-t "@scenario_001" MODE=headless"
50
+ ```
51
+ This will run the tests in headless mode
52
+
53
+ ## To open allure results
54
+ ```
55
+ allure serve reports/allure
56
+ ```
57
+
58
+ ## Multiple Browser
59
+ Currently supports for Chrome browser, but handled in such a way that framework can be easily configured to support multiple browsers. I used webdriver manager to resolve the driver-browser compatibility issues, use the same to add your designated browser (firefox, edge, ie, safari etc.,).
60
+
61
+ ## Multi Browser
62
+ Initiate the driver class inside support package mutiple times with different WebDriver objects. You can execute the actions in multiple browsers at the same time by executing actions against each driver object.
63
+
64
+ ## Reports
65
+ For better illustration on the testcases, allure reports has been integrated. Allure reports can also be integrated with jenkins to get a dashboard view. Apart from allure, cucumber's default reporting such as html, pretty, progress, rerun files has been added to the `reports/` folder.
66
+
67
+ ## Jenkins Integration with Docker images
68
+ Get any of the linux with ruby docker image as the slaves in jenkins and use the same for executing the UI automation with this framework (Sample docker image - `https://hub.docker.com/_/ruby`). From the jenkins bash Execute the following to get the testcases to run,
69
+ ```
70
+ #!/bin/bash -l
71
+ rvm list
72
+ ls
73
+ cd <path_to_the_project>
74
+ bundle install
75
+ cucumber #or custom commands
76
+ ```
77
+ for complete guide to setup in linux check [Cloud Setup for Ruby](https://github.com/nareshnavinash/Cloud-Setup-Ruby)
78
+
79
+ In Jenkins pipeline, try to add the following snippet to execute the tests,
80
+ ```
81
+ pipeline {
82
+ agent { docker { image 'ruby' } }
83
+ stages {
84
+ stage('build') {
85
+ steps {
86
+ sh 'cd project/'
87
+ sh 'gem install bundler'
88
+ sh 'bundle install'
89
+ sh 'cucumber' # or custom methods
90
+ }
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Headless Run
97
+ In `global-data/global.yml` file, if the mode is `headless`, the chrome will be initialized in headless mode which can be used to run in server. Screenshots will be added even if the browser runs in headless mode.
98
+
99
+ ## Break down into end to end tests
100
+
101
+ ### Adding Locators to the project
102
+
103
+ 1. Add Locators to the that are going to be used inside the project inside the `Locators` module
104
+ ```
105
+ module Locators
106
+ # Add a class for each page and add the locators
107
+ end
108
+ ```
109
+ 2. For each page add a new class inside the `Locators` module.
110
+
111
+ ```
112
+ module Locators
113
+ class TestPage
114
+
115
+ # All the Locators in the initialize block need to be declared here for read write permission.
116
+ attr_accessor :TEST_LOCATOR
117
+
118
+ def initialize
119
+ # Locators can be declared here by mentioning {how?(xpath,css,id) and what?(identifier)}
120
+ @TEST_LOCATOR = Locator.new(:id, "")
121
+ end
122
+
123
+ # Dynamic locators can be declared here as a seperate method (This method doesnot need to be declared with attr_accessor)
124
+ def TEST_DYNAMIC_LOCATOR(variable)
125
+ @TEST_DYNAMIC_LOCATOR = Locator.new(:xpath,"//*[text()=#{variable}]")
126
+ end
127
+
128
+ end
129
+ end
130
+ ```
131
+
132
+ 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).
133
+ * 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.
134
+
135
+ ### Adding page methods to the project
136
+
137
+ 1. Add page specific methods inside the `Pages` module.
138
+
139
+ ```
140
+ module Pages
141
+ # add the page class here
142
+ end
143
+ ```
144
+
145
+ 2. For each page add a new class inside `Pages` module and each page class should inherit the locators class of the same page
146
+
147
+ ```
148
+ module Pages
149
+ class TestPage < Locators::TestPage
150
+
151
+ def initialize()
152
+ super()
153
+ end
154
+
155
+ def test_method(attribute_text)
156
+ puts "#{attribute_text}"
157
+ end
158
+
159
+ end
160
+ end
161
+ ```
162
+
163
+ 3. Ideally each web page should have a new page file inside `pages` folder with the class name same as the web page name.
164
+ * 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.
165
+
166
+ ### Creating a new feature file in the project
167
+
168
+ 1. Define the tests in the feature file in gherkin language.
169
+
170
+ ```
171
+ Feature: Sample project setup
172
+ To get to know the sample cucumber project
173
+
174
+ Scenario: This test will pass
175
+ Given true eql true
176
+ When false eql false
177
+ Then string eql string
178
+ ```
179
+
180
+ 2. Ideally tags has to be used for each feature and each scenario to identify the test cases in the unique way.
181
+
182
+ ```
183
+ @before_feature @test_feature
184
+ Feature: Sample project setup
185
+ To get to know about the basic flows in this framework
186
+
187
+ @before_scenario @test_id=001
188
+ Scenario: This test will pass
189
+ Given true eql true
190
+ When false eql false
191
+ Then string eql string
192
+ ```
193
+
194
+ 3. Now declare the feature steps inside the step definitions file, the name of the step definition file should be same as the feature file.
195
+
196
+ 4. In the step definitions file, initially declare the before and after action block.
197
+
198
+ ```
199
+ Before do
200
+ puts "before each "
201
+ end
202
+
203
+ After do |s|
204
+ puts "after each "
205
+ end
206
+ ```
207
+
208
+ 5. Cucumber allows us to use in an extensive way. So we can define `Before` and `After` for each specific tags that we defined in the feature file.
209
+
210
+ ```
211
+ Before('@test_tag') do
212
+ puts "before each "
213
+ end
214
+
215
+ After('@test_tag') do |s|
216
+ puts "after each "
217
+ end
218
+ ```
219
+
220
+ 6. Define the steps after the before/after block.
221
+
222
+ ```
223
+ Given("true eql true") do
224
+ expect(true).to eql true
225
+ end
226
+
227
+ When("false eql false") do
228
+ expect(false).to eql false
229
+ end
230
+
231
+ Then("string eql string") do
232
+ expect("test").to eql "test"
233
+ end
234
+ ```
235
+
236
+ ## Built With
237
+
238
+ * [Cucumber](https://rubygems.org/gems/cucumber/versions/3.1.2) - Automation core framework
239
+ * [Parallel_tests](https://rubygems.org/gems/parallel_tests) - To run automation parallely at the same time.
240
+ * [Allure Cucumber](https://rubygems.org/gems/allure-cucumber/versions/0.6.1) - For Detailed reporting.
241
+ * [Selenium](https://www.seleniumhq.org/) - For web browser automation.
242
+
243
+ ## Contributing
244
+
245
+ 1. Clone the repo!
246
+ 2. Create your feature branch: `git checkout -b my-new-feature`
247
+ 3. Commit your changes: `git commit -am 'Add some feature'`
248
+ 4. Push to the branch: `git push origin my-new-feature`
249
+ 5. Create a pull request.
250
+
251
+ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on code of conduct, and the process for submitting pull requests.
252
+
253
+ ## Authors
254
+
255
+ * **[Naresh Sekar](https://github.com/nareshnavinash)**
256
+
257
+ ## License
258
+
259
+ This project is licensed under the GNU GPL-3.0 License - see the [LICENSE](LICENSE) file for details
260
+
261
+ ## Acknowledgments
262
+
263
+ * To all the open source contributors whose code has been referred in this project.
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-cayman
@@ -0,0 +1,2 @@
1
+ default: --color --format AllureCucumber::Formatter --out reports/allure --format html --out reports/html/html_result.html --format ParallelTests::Cucumber::FailuresLogger --out reports/parallel_failures_log/cucumber_failures.log --format rerun --out reports/cucumber_rerun/rerun.txt --format progress --out reports/progress/progress.txt --format pretty --out reports/pretty/pretty.txt --format pretty
2
+ parallel: --color --format AllureCucumber::Formatter --out reports/allure --format html --out reports/html/html_result<%= ENV['TEST_ENV_NUMBER']%>.html --format ParallelTests::Cucumber::FailuresLogger --out reports/parallel_failures_log/cucumber_failures<%= ENV['TEST_ENV_NUMBER']%>.log --format rerun --out reports/cucumber_rerun/rerun<%= ENV['TEST_ENV_NUMBER']%>.txt --format progress --out reports/progress/progress<%= ENV['TEST_ENV_NUMBER']%>.txt --format pretty --out reports/pretty/pretty<%= ENV['TEST_ENV_NUMBER']%>.txt --format pretty
Binary file
File without changes
@@ -0,0 +1,27 @@
1
+ @TC_Google_Search
2
+ Feature: Search for a term in google search
3
+ Entering a term in google search and verifying result page is displayed
4
+
5
+ @scenario_001 @regression @sanity
6
+ Scenario: Single term serach
7
+ Given I navigate to google search page
8
+ When I type the term in google search bar and click on serach results
9
+ Then I should get the results page
10
+
11
+ @scenario_002
12
+ Scenario Outline: Multiple search items in google using scenario outline
13
+ Given I navigate to google search page
14
+ When I type the "<Term>" in google search bar and click on serach results
15
+ Then I should get the results page
16
+
17
+ @regression
18
+ Examples:
19
+ | Term |
20
+ | Hello |
21
+ | Hi |
22
+ | Where |
23
+
24
+ @sanity
25
+ Examples:
26
+ | Term |
27
+ | Hello |
@@ -0,0 +1,9 @@
1
+ @TC_Google_Search
2
+ Feature: Search for a term in google search
3
+ Entering a term in google search and verifying result page is displayed
4
+
5
+ @scenario_001 @regression @sanity
6
+ Scenario: Single term serach
7
+ Given I navigate to google search page
8
+ When I type the term in google search bar and click on serach results
9
+ Then I should get the results page
File without changes
@@ -0,0 +1,4 @@
1
+ browser: chrome
2
+ implicit_wait: 10
3
+ screenshot_location: reports/screenshots
4
+ mode: UI
File without changes
@@ -0,0 +1,31 @@
1
+ [
2
+ {
3
+ "name": "Skipped tests",
4
+ "messageRegex": ".*",
5
+ "matchedStatuses": [ "skipped" ]
6
+ },
7
+ {
8
+ "name": "Element not found",
9
+ "traceRegex": ".*NoSuchElementError.*",
10
+ "matchedStatuses": [ "failed" ]
11
+ },
12
+ {
13
+ "name": "Broken tests",
14
+ "traceRegex": "Error.*",
15
+ "matchedStatuses": [ "failed"]
16
+ },
17
+ {
18
+ "name": "Test Script defect",
19
+ "messageRegex": ".*Expected is not a String or a RegExp.*",
20
+ "matchedStatuses": ["failed"]
21
+ },
22
+ {
23
+ "name": "Element not found Defect",
24
+ "messageRegex": ".*no such element.*",
25
+ "matchedStatuses": ["failed"]
26
+ },
27
+ {
28
+ "name": "Passed tests",
29
+ "matchedStatuses": ["passed"]
30
+ }
31
+ ]
@@ -0,0 +1,212 @@
1
+ # module Libraries
2
+
3
+ # class Driver
4
+ # attr_accessor :driver
5
+ # $focus_driver = nil
6
+ # @driver = nil
7
+ # @main_window = nil
8
+ # @click_exception_count = nil
9
+ # @@drivers = []
10
+ # @@drivers_with_names = {}
11
+
12
+ # def initialize(driver_name = "Driver", browser = $conf["browser"])
13
+ # begin
14
+ # start(driver_name,browser)
15
+ # puts "#{driver_name} is initialized"
16
+ # rescue Exception => e
17
+ # puts "#{driver_name} is failed to initialize \n\n #{e.backtrace}\n\nRetrying to initialize #{driver_name}"
18
+ # start(driver_name,browser)
19
+ # puts "#{driver_name} is initialized after an exception"
20
+ # end
21
+ # end
22
+
23
+ # ##############################
24
+ # # Custom methods of driver #
25
+ # ##############################
26
+
27
+ # def start(driver_name, browser)
28
+
29
+ # case browser
30
+
31
+ # when 'chrome'
32
+ # options = Selenium::WebDriver::Chrome::Options.new
33
+ # if ENV['MODE'] == "headless" or $conf["mode"] == "headless"
34
+ # switches = ["disable-infobars", "disable-gpu", "disable-dev-shm-usage", "no-sandbox", "headless"]
35
+ # else
36
+ # switches = ["disable-infobars", "disable-gpu", "disable-dev-shm-usage", "no-sandbox"]
37
+ # end
38
+ # switches.map { |k| options.add_argument(k) }
39
+ # @driver = Selenium::WebDriver.for(:chrome, options: options)
40
+ # @driver.manage.timeouts.implicit_wait = $conf["implicit_wait"]
41
+
42
+ # when 'firefox', 'ff'
43
+ # # to be added
44
+
45
+ # when 'ie', 'internet_explorer'
46
+ # # to be added
47
+
48
+ # when 'edge'
49
+ # # to be added
50
+
51
+ # when 'safari'
52
+ # # to be added
53
+
54
+ # else
55
+ # raise ArgumentError, "Specify a proper browser while initiating a driver \n \n#{browser.inspect}"
56
+ # end
57
+
58
+ # target_size = Selenium::WebDriver::Dimension.new(1200, 700)
59
+ # @driver.manage.window.size = target_size
60
+ # @click_exception_count=0
61
+ # @@drivers.push(self)
62
+ # @@drivers_with_names[self] = "#{driver_name}"
63
+ # $focus_driver = self
64
+ # puts "#{driver_name} - #{self}"
65
+ # return self
66
+ # end
67
+
68
+ # def get(url)
69
+ # $focus_driver = self
70
+ # @driver.get(url)
71
+ # puts "#{$focus_driver} loaded with - #{url}"
72
+ # end
73
+
74
+ # def refresh
75
+ # $focus_driver = self
76
+ # navigate.refresh
77
+ # puts "#{$focus_driver} is refreshed"
78
+ # end
79
+
80
+ # def find_element(locator)
81
+ # $focus_driver = self
82
+ # Libraries::Wait.wait_for_element(locator)
83
+ # return @driver.find_element(locator.how,locator.what)
84
+ # end
85
+
86
+ # def find_elements(locator)
87
+ # $focus_driver = self
88
+ # return @driver.find_elements(locator.how,locator.what)
89
+ # end
90
+
91
+ # def mouse_over(locator,index=1)
92
+ # $focus_driver = self
93
+ # element=find_elements(locator)[index-1]
94
+ # @driver.action.move_to(element).perform
95
+ # puts "mouse over for the element - #{locator.how} => #{locator.what} is done"
96
+ # end
97
+
98
+ # def mouse
99
+ # $focus_driver = self
100
+ # return @driver.mouse
101
+ # end
102
+
103
+ # def action
104
+ # $focus_driver = self
105
+ # return @driver.action
106
+ # end
107
+
108
+ # def move_and_click(locator)
109
+ # $focus_driver = self
110
+ # ele=find_element(locator)
111
+ # @driver.action.move_to(ele).click.perform
112
+ # puts "Mouse over the locator and then click for - #{locator.how} => #{locator.what} is done"
113
+ # end
114
+
115
+ # def current_url
116
+ # $focus_driver = self
117
+ # @driver.current_url
118
+ # end
119
+
120
+ # def save_screenshot(file_name = nil)
121
+ # $focus_driver = self
122
+ # file_name = "#{Pathname.pwd}/#{$conf['screenshot_location']}/#{Time.new.strftime("%Y-%m-%d-%H-%M-%S-%L-%N")}.png" if file_name.nil?
123
+ # puts "#{$focus_driver}'s Screenshot saved in this path => #{file_name}"
124
+ # @driver.save_screenshot(file_name)
125
+ # end
126
+
127
+ # def switch_to_frame(locator)
128
+ # $focus_driver = self
129
+ # @main_window=@driver.window_handle
130
+ # @driver.switch_to.frame(find_element(locator))
131
+ # puts "Switched to iframe - #{locator.how} => #{locator.what} on #{$focus_driver}"
132
+ # return @main_window
133
+ # end
134
+
135
+ # def switch_to_window(locator=nil)
136
+ # $focus_driver = self
137
+ # @main_window=@driver.window_handle
138
+ # locator.click if locator != nil
139
+ # windows=@driver.window_handles
140
+ # new_window=nil;
141
+ # windows.length.times do |i|
142
+ # if windows[i] != @main_window
143
+ # new_window=windows[i]
144
+ # end
145
+ # end
146
+ # @driver.switch_to.window(new_window)
147
+ # puts "Switched to new window on #{$focus_driver}"
148
+ # return @main_window
149
+ # end
150
+
151
+ # def scroll_to_locator(locator)
152
+ # $focus_driver = self
153
+ # element = find_element(locator)
154
+ # @driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});",element)
155
+ # puts "Scroll to this locator - #{locator.how} => #{locator.what} on #{$focus_driver}"
156
+ # sleep 1
157
+ # end
158
+
159
+ # def revert_to(window=nil)
160
+ # $focus_driver = self
161
+ # if window != nil
162
+ # @driver.switch_to.window(window)
163
+ # puts "Switched back to another window - #{window} in #{$focus_driver}"
164
+ # else
165
+ # @driver.switch_to.window(@main_window)
166
+ # puts "Switched back to main window in #{focus_driver}"
167
+ # end
168
+ # end
169
+
170
+ # def close
171
+ # $focus_driver = self
172
+ # @driver.close
173
+ # puts "Closed the browser - #{$focus_driver}"
174
+ # end
175
+
176
+ # def quit
177
+ # @driver.quit
178
+ # @@drivers.delete(self)
179
+ # $focus_driver = @@drivers[0]
180
+ # puts "Quit the browser - #{$focus_driver}"
181
+ # end
182
+
183
+ # def quit_all
184
+ # @@drivers.each do |driver|
185
+ # driver.quit if driver != self
186
+ # end
187
+ # self.quit
188
+ # puts "deleted all the browsers"
189
+ # end
190
+
191
+ # def self.quit_all_drivers
192
+ # @@drivers.each do |driver|
193
+ # driver.quit if driver != self
194
+ # end
195
+ # puts "deleted all the browsers"
196
+ # end
197
+
198
+ # def self.get_all_drivers
199
+ # return @@drivers_with_names
200
+ # end
201
+
202
+ # def self.get_current_driver
203
+ # return $focus_driver
204
+ # end
205
+
206
+ # def self.switch_to(driver)
207
+ # $focus_driver = driver
208
+ # end
209
+
210
+ # end
211
+ # end
212
+