howitzer 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +32 -0
  4. data/.travis.yml +1 -4
  5. data/.yardopts +1 -2
  6. data/CHANGELOG.md +28 -1
  7. data/Gemfile +6 -0
  8. data/LICENSE +1 -1
  9. data/README.md +55 -85
  10. data/Rakefile +7 -7
  11. data/bin/howitzer +56 -31
  12. data/features/cli_new.feature +162 -79
  13. data/features/cli_update.feature +114 -21
  14. data/features/step_definitions/common_steps.rb +29 -9
  15. data/features/support/env.rb +1 -1
  16. data/features/support/transformers.rb +2 -2
  17. data/generators/base_generator.rb +121 -49
  18. data/generators/config/config_generator.rb +8 -5
  19. data/generators/config/templates/boot.rb +14 -0
  20. data/generators/config/templates/capybara.rb +156 -0
  21. data/generators/config/templates/custom.yml +2 -3
  22. data/generators/config/templates/default.yml +50 -82
  23. data/generators/cucumber/cucumber_generator.rb +9 -9
  24. data/generators/cucumber/templates/common_steps.rb +4 -4
  25. data/generators/cucumber/templates/cucumber.rake +63 -54
  26. data/generators/cucumber/templates/env.rb +24 -23
  27. data/generators/cucumber/templates/transformers.rb +23 -15
  28. data/generators/emails/emails_generator.rb +4 -2
  29. data/generators/emails/templates/example_email.rb +4 -4
  30. data/generators/prerequisites/prerequisites_generator.rb +24 -0
  31. data/generators/prerequisites/templates/base.rb +22 -0
  32. data/generators/prerequisites/templates/factory_girl.rb +30 -0
  33. data/generators/prerequisites/templates/user.rb +7 -0
  34. data/generators/prerequisites/templates/users.rb +12 -0
  35. data/generators/root/root_generator.rb +11 -7
  36. data/generators/root/templates/.rubocop.yml +32 -0
  37. data/generators/root/templates/Gemfile.erb +27 -0
  38. data/generators/root/templates/Rakefile +6 -8
  39. data/generators/rspec/rspec_generator.rb +7 -7
  40. data/generators/rspec/templates/example_spec.rb +1 -1
  41. data/generators/rspec/templates/rspec.rake +48 -29
  42. data/generators/rspec/templates/spec_helper.rb +33 -32
  43. data/generators/tasks/tasks_generator.rb +4 -2
  44. data/generators/tasks/templates/common.rake +1 -16
  45. data/generators/turnip/templates/.rspec +1 -0
  46. data/generators/turnip/templates/common_steps.rb +25 -0
  47. data/generators/turnip/templates/example.feature +8 -0
  48. data/generators/turnip/templates/spec_helper.rb +56 -0
  49. data/generators/turnip/templates/turnip.rake +61 -0
  50. data/generators/turnip/templates/turnip_helper.rb +6 -0
  51. data/generators/turnip/turnip_generator.rb +26 -0
  52. data/generators/web/templates/example_page.rb +15 -0
  53. data/generators/web/templates/menu_section.rb +13 -0
  54. data/generators/web/web_generator.rb +22 -0
  55. data/howitzer.gemspec +14 -21
  56. data/lib/howitzer.rb +47 -7
  57. data/lib/howitzer/cache.rb +70 -0
  58. data/lib/howitzer/capybara_helpers.rb +194 -0
  59. data/lib/howitzer/email.rb +96 -104
  60. data/lib/howitzer/exceptions.rb +10 -6
  61. data/lib/howitzer/log.rb +120 -0
  62. data/lib/howitzer/mail_adapters.rb +7 -0
  63. data/lib/howitzer/mail_adapters/abstract.rb +84 -0
  64. data/lib/howitzer/mail_adapters/mailgun.rb +115 -0
  65. data/lib/howitzer/mailgun_api.rb +9 -0
  66. data/lib/howitzer/mailgun_api/client.rb +79 -0
  67. data/lib/howitzer/mailgun_api/connector.rb +37 -0
  68. data/lib/howitzer/mailgun_api/response.rb +28 -0
  69. data/lib/howitzer/tasks/framework.rake +2 -2
  70. data/lib/howitzer/utils.rb +7 -1
  71. data/lib/howitzer/utils/string_extensions.rb +66 -0
  72. data/lib/howitzer/version.rb +2 -1
  73. data/lib/howitzer/web.rb +11 -0
  74. data/lib/howitzer/web/base_section.rb +27 -0
  75. data/lib/howitzer/web/blank_page.rb +12 -0
  76. data/lib/howitzer/web/capybara_methods_proxy.rb +29 -0
  77. data/lib/howitzer/web/element_dsl.rb +109 -0
  78. data/lib/howitzer/web/iframe_dsl.rb +93 -0
  79. data/lib/howitzer/web/page.rb +173 -0
  80. data/lib/howitzer/web/page_dsl.rb +64 -0
  81. data/lib/howitzer/web/page_validator.rb +118 -0
  82. data/lib/howitzer/web/section.rb +27 -0
  83. data/lib/howitzer/web/section_dsl.rb +154 -0
  84. data/spec/config/custom.yml +10 -1
  85. data/spec/spec_helper.rb +37 -19
  86. data/spec/support/generator_helper.rb +12 -11
  87. data/spec/support/logger_helper.rb +10 -9
  88. data/spec/support/mailgun_unit_client.rb +52 -44
  89. data/spec/support/shared_examples/capybara_context_holder.rb +33 -0
  90. data/spec/support/shared_examples/capybara_methods_proxy.rb +94 -0
  91. data/spec/support/shared_examples/dynamic_section_methods.rb +35 -0
  92. data/spec/support/shared_examples/element_dsl.rb +119 -0
  93. data/spec/unit/generators/base_generator_spec.rb +64 -33
  94. data/spec/unit/generators/config_generator_spec.rb +11 -7
  95. data/spec/unit/generators/cucumber_generator_spec.rb +26 -17
  96. data/spec/unit/generators/emails_generator_spec.rb +10 -6
  97. data/spec/unit/generators/prerequisites_generator_spec.rb +53 -0
  98. data/spec/unit/generators/root_generator_spec.rb +50 -13
  99. data/spec/unit/generators/rspec_generator_spec.rb +9 -9
  100. data/spec/unit/generators/tasks_generator_spec.rb +6 -6
  101. data/spec/unit/generators/turnip_generator_spec.rb +52 -0
  102. data/spec/unit/generators/web_generator_spec.rb +52 -0
  103. data/spec/unit/lib/cache_spec.rb +85 -0
  104. data/spec/unit/lib/capybara_helpers_spec.rb +696 -0
  105. data/spec/unit/lib/email_spec.rb +104 -91
  106. data/spec/unit/lib/howitzer.rb +31 -0
  107. data/spec/unit/lib/init_spec.rb +0 -1
  108. data/spec/unit/lib/log_spec.rb +122 -0
  109. data/spec/unit/lib/mail_adapters/abstract_spec.rb +62 -0
  110. data/spec/unit/lib/mail_adapters/mailgun_spec.rb +163 -0
  111. data/spec/unit/lib/mailgun_api/client_spec.rb +58 -0
  112. data/spec/unit/lib/mailgun_api/connector_spec.rb +54 -0
  113. data/spec/unit/lib/mailgun_api/response_spec.rb +28 -0
  114. data/spec/unit/lib/utils/string_extensions_spec.rb +77 -0
  115. data/spec/unit/lib/web/base_section_spec.rb +41 -0
  116. data/spec/unit/lib/web/element_dsl_spec.rb +17 -0
  117. data/spec/unit/lib/web/iframe_dsl_spec.rb +99 -0
  118. data/spec/unit/lib/web/page_dsl_spec.rb +52 -0
  119. data/spec/unit/lib/web/page_spec.rb +304 -0
  120. data/spec/unit/lib/web/page_validator_spec.rb +218 -0
  121. data/spec/unit/lib/web/section_dsl_spec.rb +165 -0
  122. data/spec/unit/lib/web/section_spec.rb +61 -0
  123. data/spec/unit/version_spec.rb +1 -1
  124. metadata +116 -203
  125. data/GETTING_STARTED.md +0 -774
  126. data/generators/cucumber/templates/cucumber.yml +0 -10
  127. data/generators/pages/pages_generator.rb +0 -21
  128. data/generators/pages/templates/example_menu.rb +0 -15
  129. data/generators/pages/templates/example_page.rb +0 -15
  130. data/generators/root/templates/Gemfile +0 -7
  131. data/generators/root/templates/boot.rb +0 -10
  132. data/lib/howitzer/blank_page.rb +0 -6
  133. data/lib/howitzer/capybara/dsl_ex.rb +0 -15
  134. data/lib/howitzer/capybara/settings.rb +0 -343
  135. data/lib/howitzer/helpers.rb +0 -230
  136. data/lib/howitzer/init.rb +0 -1
  137. data/lib/howitzer/mailgun/client.rb +0 -65
  138. data/lib/howitzer/mailgun/connector.rb +0 -34
  139. data/lib/howitzer/mailgun/response.rb +0 -28
  140. data/lib/howitzer/patches/rawler_patched.rb +0 -86
  141. data/lib/howitzer/settings.rb +0 -27
  142. data/lib/howitzer/utils/data_generator/data_storage.rb +0 -88
  143. data/lib/howitzer/utils/data_generator/gen.rb +0 -135
  144. data/lib/howitzer/utils/locator_store.rb +0 -217
  145. data/lib/howitzer/utils/log.rb +0 -139
  146. data/lib/howitzer/utils/page_validator.rb +0 -133
  147. data/lib/howitzer/vendor/firebug-1.12.1-fx.xpi +0 -0
  148. data/lib/howitzer/vendor/firepath-0.9.7-fx.xpi +0 -0
  149. data/lib/howitzer/web_page.rb +0 -253
  150. data/spec/active_resource.rb +0 -0
  151. data/spec/config/default.yml +0 -26
  152. data/spec/support/boot_helper.rb +0 -15
  153. data/spec/unit/generators/pages_generator_spec.rb +0 -33
  154. data/spec/unit/lib/capybara/dsl_ex_spec.rb +0 -60
  155. data/spec/unit/lib/capybara/settings_spec.rb +0 -441
  156. data/spec/unit/lib/helpers_spec.rb +0 -1129
  157. data/spec/unit/lib/mailgun/client_spec.rb +0 -36
  158. data/spec/unit/lib/mailgun/connector_spec.rb +0 -70
  159. data/spec/unit/lib/mailgun/response_spec.rb +0 -28
  160. data/spec/unit/lib/settings_spec.rb +0 -17
  161. data/spec/unit/lib/utils/data_generator/data_storage_spec.rb +0 -80
  162. data/spec/unit/lib/utils/data_generator/gen_spec.rb +0 -90
  163. data/spec/unit/lib/utils/locator_store_spec.rb +0 -157
  164. data/spec/unit/lib/utils/log_spec.rb +0 -107
  165. data/spec/unit/lib/utils/page_validator_spec.rb +0 -265
  166. data/spec/unit/lib/web_page_spec.rb +0 -346
@@ -1,774 +0,0 @@
1
- Getting Started
2
- ===============
3
-
4
- Available Drivers
5
- ------
6
-
7
- **Driver** is a universal interface for test runners against various web browsers. All driver implementations can be divided into 2 categories:
8
-
9
- * **Headless testing** – a browser emulation without a GUI (very useful on CI servers, e.g. Bamboo, TeamCity, Jenkins, etc.).
10
- * **Real browser testing** - an integration with real browsers through extensions, plugins, ActiveX, etc., (for local and cloud based testing, like SauceLabs, Testingbot, BrowserStack).
11
-
12
- Howitzer uses [Capybara](http://jnicklas.github.io/capybara/) for the driver management and configuration. All you need to do is to:
13
-
14
- - specify the **driver** settings in the _config/default.yml_
15
- - Specify a few extra settings for the selected driver.
16
-
17
- The table below gives an important information on the driver settings in Howitzer:
18
-
19
- <table>
20
- <thead>
21
- <tr>
22
- <th>Driver</th>
23
- <th align="center">Category</th>
24
- <th align="center">Setting name</th>
25
- <th align="center">Setting type</th>
26
- <th align="center">Description</th>
27
- </tr>
28
- </thead>
29
- <tbody>
30
- <tr>
31
- <td>
32
- <a href="http://phantomjs.org/">phantomjs</a>(<strong>default</strong>)<br/><br/>
33
- <a href="https://github.com/teampoltergeist/poltergeist">poltergeist</a>
34
- </td>
35
- <td align="center">Headless</td>
36
- <td align="center">
37
- <strong>pjs_ignore_js_errors</strong><br/><br/>
38
- <strong>pjs_ignore_ssl_errors</strong>
39
- </td>
40
- <td align="center">
41
- Boolean <br/><br/>
42
- Boolean
43
- </td>
44
- <td align="center">
45
- if false, then raises exception on js error in app<br/>
46
- if false, then ignores ssl warnings<br/>
47
- </td>
48
- </tr>
49
-
50
- <tr>
51
- <td><a href="https://github.com/thoughtbot/capybara-webkit">webkit</a></td>
52
- <td align="center">Headless</td>
53
- <td align="center">-</td>
54
- <td align="center">-</td>
55
- <td align="center">Uncomment `gem 'capybara-webkit'` in Gemfile</td>
56
- </tr>
57
- <tr>
58
- <td><a href="https://code.google.com/p/selenium/wiki/RubyBindings">selenium</a></td>
59
- <td align="center">Real</td>
60
- <td align="center"><strong>sel_browser</strong></td>
61
- <td align="center">String</td>
62
- <td align="center">Indicate one of the following browsers: iexplore (ie), firefox (ff), chrome, opera, safari.</td>
63
- </tr>
64
- <tr>
65
- <td><a href="http://docs.seleniumhq.org/docs/07_selenium_grid.jsp">selenium_grid</a></td>
66
- <td align="center">Real</td>
67
- <td align="center"><strong>sel_hub_url<br/>sel_browser<br/><br/><br/></strong></td>
68
- <td align="center">String<br/>String<br/><br/><br/></td>
69
- <td align="center">Hub url<br/>Indicate one of the following browsers: iexplore (ie), firefox (ff), chrome, opera, safari.</td>
70
- </tr>
71
- <tr>
72
- <td>selenium_dev</td>
73
- <td align="center">Real</td>
74
- <td align="center"><strong>-</strong></td>
75
- <td align="center">-</td>
76
- <td align="center">Execute tests against FireFox (with Firebug and FirePath extensions).</td>
77
- </tr>
78
- <tr>
79
- <td><a href="https://saucelabs.com">sauce</a></td>
80
- <td align="center">Real</td>
81
- <td align="center">
82
- <strong>sl_user<strong><br/>
83
- <strong>sl_api_key</strong><br/>
84
- <strong>sl_url</strong><br/>
85
- <strong>sl_platform</strong><br/>
86
- <strong>sl_browser_name</strong><br/>
87
- <strong>sl_selenium_version</strong><br/>
88
- <strong>sl_max_duration</strong><br/>
89
- <strong>sl_idle_timeout</strong></td>
90
- <td align="center">
91
- String<br/>
92
- String<br/>
93
- String<br/>
94
- Symbol<br/>
95
- String<br/>
96
- String<br/>
97
- String<br/>
98
- String</td>
99
- <td align="center">See details <a href="https://saucelabs.com/docs/additional-config">here</a></td>
100
- </tr>
101
- <tr>
102
- <td><a href="http://testingbot.com">testingbot</a></td>
103
- <td align="center">Real</td>
104
- <td align="center">
105
- <strong>tb_api_key<strong><br/>
106
- <strong>tb_api_secret<strong><br/>
107
- <strong>tb_url<strong><br/>
108
- <strong>tb_platform<strong><br/>
109
- <strong>tb_browser_name<strong><br/>
110
- <strong>tb_browser_version<strong><br/>
111
- <strong>tb_selenium_version<strong><br/>
112
- <strong>tb_max_duration<strong><br/>
113
- <strong>tb_idle_timeout<strong><br/>
114
- <strong>tb_record_screenshot<strong>
115
- </td>
116
- <td align="center">
117
- String<br/>
118
- String<br/>
119
- String<br/>
120
- Symbol<br/>
121
- String<br/>
122
- Numberic<br/>
123
- String<br/>
124
- String<br/>
125
- String<br/>
126
- Boolean</td>
127
- <td align="center">See details <a href="http://testingbot.com/support/other/test-options">here</a></td>
128
- </tr>
129
- </tbody>
130
- </table>
131
-
132
- Pages
133
- ------
134
-
135
- Pages are classes describing real web pages. For example, 'Home page' can be described as:
136
-
137
- ```ruby
138
- class HomePage < WebPage
139
- end
140
- ```
141
-
142
- It means that each page is inherited from a parent class 'Web Page' which contains common methods for all pages.
143
-
144
- Every page contains a required constant URL (the relative URL of the page):
145
-
146
- **Example:**
147
-
148
- ```ruby
149
- # put the class to ./pages/home_page.rb file
150
-
151
- class HomePage < WebPage
152
- URL = '/'
153
- end
154
- ```
155
-
156
- ### Validations
157
-
158
- The Page Object pattern is not expected to use any validations on the UI driver level. But at the same time every page must have some anchor to identify a page exclusively.
159
-
160
- ```ruby
161
- validates <type>, options
162
- ```
163
-
164
- Howitzer provides 3 different validation types:
165
-
166
- <table>
167
- <thead>
168
- <tr>
169
- <th align="center">Validation Type</th>
170
- <th align="center">Options</th>
171
- <th align="center">Value Type</th>
172
- <th align="center">Description</th>
173
- </tr>
174
- </thead>
175
- <tbody>
176
- <tr>
177
- <td>:url</td>
178
- <td>pattern</td>
179
- <td>Regexp</td>
180
- <td>matches current url to pattern</td>
181
- </tr>
182
- <tr>
183
- <td>:title</td>
184
- <td>pattern</td>
185
- <td>Regexp</td>
186
- <td>matches current pate title to pattern</td>
187
- </tr>
188
- <tr>
189
- <td>:element_presence</td>
190
- <td>locator</td>
191
- <td>String/Symbol</td>
192
- <td>find element by locator on current page</td>
193
- </tr>
194
- </tbody>
195
- </table>
196
-
197
- **Example 1:**
198
-
199
- ```ruby
200
- class HomePage < WebPage
201
- URL = '/'
202
- validates :url, pattern: /\A(?:.*?:\/\/)?[^\/]*\/?\z/
203
- end
204
- ```
205
-
206
- **Example 2:**
207
-
208
- ```ruby
209
- class LoginPage < WebPage
210
- URL = '/users/sign_in'
211
- validates :title, pattern: /Sign In\z/
212
- end
213
- ```
214
-
215
- **Example 3:**
216
-
217
- ```ruby
218
- class LoginPage < WebPage
219
- URL = '/users/sign_in'
220
-
221
- validates :element_presence, locator: :sign_in_btn
222
-
223
- add_locator :sign_in_btn, '#sign_in'
224
- end
225
- ```
226
-
227
- Howitzer allows using all 3 validations, but only 1 is really required. If any validation fails, the exception will appear.
228
-
229
- **CAUTION:** Page validation is triggered in 2 cases only:
230
-
231
- 1. < Web Page Class >.open(url)
232
- 2. < Web Page Class >.given
233
-
234
-
235
- ### Locators ###
236
-
237
- Locator is a search item (selector) of one or more elements on a 'Web page'.
238
-
239
- The table below lists the types of locators, the possible methods of searching and Capybara methods, which may be called.
240
-
241
- <table>
242
- <thead>
243
- <tr>
244
- <th align="center">Locator Type</th>
245
- <th align="center">Search Methods</th>
246
- <th align="center">Capybara Methods</th>
247
- </tr>
248
- </thead>
249
- <tbody>
250
- <tr>
251
- <td>:locator</td>
252
- <td>css(by default), xpath</td>
253
- <td>find, all, first</td>
254
- </tr>
255
- <tr>
256
- <td>:link_locator</td>
257
- <td>id, text </td>
258
- <td>click_link, find_link</td>
259
- </tr>
260
- <tr>
261
- <td>:field_locator</td>
262
- <td>id, name, text</td>
263
- <td>find_field, fill_in</td>
264
- </tr>
265
- <tr>
266
- <td>:button_locator</td>
267
- <td>id, name, text</td>
268
- <td>click_button, find_button</td>
269
- </tr>
270
- </tbody>
271
- </table>
272
-
273
- Each page contains a description of all elements by adding the appropriate locators that are preceded by the prefix **add\_**
274
-
275
- **Example:**
276
-
277
- ```ruby
278
- class HomePage < WebPage
279
- URL = '/'
280
- validates :url, pattern: /\A(?:.*?:\/\/)?[^\/]*\/?\z/
281
-
282
- add_locator :test_locator_name1, '.foo' #css locator, default
283
- add_locator :test_locator_name2, css: '.foo' #css locator
284
- add_locator :test_locator_name3, xpath: '//div[@value="bar"]' #css locator
285
-
286
- add_link_locator :test_link_locator1, 'Foo' #link locator by 'Foo' text
287
- add_link_locator :test_link_locator1, 'bar' #link locator by 'bar' id
288
-
289
- add_field_locator :test_field_locator1, 'Foo' #field locator by 'Foo' text
290
- add_field_locator :test_field_locator2, 'bar' #field locator by 'bar' id
291
- add_field_locator :test_field_locator3, 'bas' #field locator by 'baz' name
292
- end
293
- ```
294
-
295
- Sometimes it needs to have universal locators, for instance for many items from menu. Another case, when it's unknown text in locator in advance. For such cases, Howitzer suggests to use _lambda_ locators.
296
-
297
- **Example:**
298
-
299
- ```ruby
300
- add_locator :menu_item, ->(name) { { xpath: ".//*[@id='main_menu']//li[.='#{ name }']/a" } }
301
-
302
- #and then usage
303
- def choose_menu(text)
304
- find(apply(locator(:menu_item), text)).click
305
- end
306
- ```
307
-
308
- ### Pages with static information ###
309
-
310
- If static information is repeated on several different pages, it can be a good idea to move these methods into a separate module.
311
-
312
- **Example:**
313
-
314
- ```ruby
315
- module TopMenu
316
- def self.included(base)
317
- base.class_eval do
318
- add_link_locator :test_link_locator1, 'Foo'
319
- end
320
- end
321
-
322
- def open_menu
323
- log.info "Open menu"
324
- click_link locator(:test_link_locator1)
325
- end
326
- end
327
- ```
328
-
329
- ### Redefining of the *open* method #####
330
-
331
- It is used when you need to open a page with additional parameters.
332
-
333
- **Example:**
334
-
335
- ```ruby
336
- class MyPage < WebPage
337
- def self.open(url="#{app_url}#{self::URL}+'?no_popup=true'")
338
- super
339
- end
340
- end
341
- ```
342
-
343
- ### Good Practices Rules ###
344
-
345
- Good Practice Rules
346
-
347
- **Rule One:** Do not get tied to the interface. This means that you should use common phrases in the name and description of the methods.
348
-
349
- **Example:**
350
-
351
- ```ruby
352
- class MyPage < WebPage
353
- def submit_form
354
- # ...
355
- end
356
-
357
- def fill_form(value)
358
- # ...
359
- end
360
- end
361
- ```
362
-
363
- **Rule Two:** Any ACTION method should return an instance of the page. This allows you to do the following:
364
-
365
- ```ruby
366
- MyPage.open.fill_form.submit_form
367
- ```
368
-
369
- **Example:**
370
-
371
- ```ruby
372
- class MyPage < WebPage
373
- def fill_form
374
- # ...
375
- MyPage.given
376
- end
377
- end
378
- ```
379
-
380
- **Rule Three:** Coding of checks in the class pages methods are __prohibited.__
381
-
382
- **Example:**
383
-
384
- ```ruby
385
- class MyPage < WebPage
386
- def submit_form
387
- # ...
388
- end
389
-
390
- def get_all_prices
391
- # ...
392
- prices
393
- end
394
- end
395
- ```
396
-
397
- my_page_spec.rb
398
- ```ruby
399
- require 'spec_helper'
400
-
401
- describe “some feature” do
402
- context “when...” do
403
- it { expect(MyPage.get_all_prices).to include(400) }
404
- end
405
- end
406
- ```
407
-
408
- **Rule Four:** All ACTION methods should create log entries.
409
-
410
- **Example:**
411
-
412
- ```ruby
413
- class MyPage < WebPage
414
- def submit_form
415
- log.info { "[ACTION] Submit form" }
416
- # ...
417
- end
418
-
419
- def fill_form
420
- log.info { "[ACTION] Fill form" }
421
- # ...
422
- end
423
- end
424
- ```
425
-
426
- Emails
427
- ------
428
-
429
- Howitzer uses an outstanding service called [Mailgun](http://mailgun.com) that allows to catch all emails of a sandbox domain and store them in its own data storage within 3 days.
430
- It is extremely useful during web application testing when a new user with email confirmation is created.
431
-
432
- You can use a **free** account. Follow the below steps to create an account:
433
-
434
- 1. Sign up [here](https://mailgun.com/signup).
435
- 2. Login and copy your API Key.
436
- 3. Open the `config/default.yml` file of your project, find the **mailgun_key** setting and paste the API key there.
437
- 4. Browse to the MailGun web page again and copy the mailgun domain, i.e. 'sandboxbaf443d4c81b43d0b64a413805dc6f68.mailgun.org'
438
- 5. Open the `config/default.yml` file of your project again, find the **mailgun_domain** setting and paste the mailgun domain there.
439
- 6. Open the MailGun web page again and navigate to the **Routes** menu.
440
- 7. Create a new route with the following parameters:
441
-
442
- <table>
443
- <thead>
444
- <tr>
445
- <th align="center">Priority</th>
446
- <th align="center">Filter Expression</th>
447
- <th align="center">Action</th>
448
- <th align="center">Description</th>
449
- </tr>
450
- </thead>
451
- <tbody>
452
- <tr>
453
- <td>0</td>
454
- <td>match_recipient(".*")</td>
455
- <td>store()</td>
456
- <td>Store all messages</td>
457
- </tr>
458
- </tbody>
459
- </table>
460
-
461
- _**Email**_ Class corresponds to one letter. Used to test the notifications.
462
-
463
- * **.find_by_recipient (recipient)** - searches for the letter recipient. The parameter receives email recipient.
464
- * **.find (recipient, subject)** - same as the **self.find_by_recipient** (recipient), but only when we do not know in advance what kind of __subject__ has an email.
465
- * **\#plain_text_body** - receiving the body of messages in a plain text.
466
- * **\#html_body** - receiving the body of messages in html.
467
- * **\#text_body** - receiving the body of messages as a stripped text.
468
- * **\#mail_from** - returns the sender’s email data in the format: User Name <user@email>
469
- * **\#recipients** - returns the array of recipients who received the current email.
470
- * **\#received_time** - returns the time when an email was received.
471
- * **\#sender_email** - returns an email of a sender.
472
- * **\#get_mime_part** - allows you receiving an email attachment.
473
-
474
- **Example:**
475
-
476
- ```ruby
477
- class MyEmail < Email
478
- SUBJECT = 'TEST SUBJECT' # specify the subject of an email
479
- end
480
- ```
481
-
482
- This is how a custom class might look like:
483
-
484
- ```ruby
485
- #put the class to ./emails/my_email.rb file
486
-
487
- class MyEmail <Email
488
- SUBJECT = "Test email" # specify the subject of an email
489
-
490
- def addressed_to? (new_user) # check that the letter were sent to proper recipient
491
- / Hi # { new_user } / === plain_text_body
492
- end
493
- end
494
- ```
495
-
496
- Logging
497
- -------
498
-
499
- *Howitzer* allows logging to the text file, HTML and output to the console.
500
-
501
- ### BUILT-IN logging ###
502
-
503
- *Howitzer* uses the resources of Cucumber and RSpec to generate HTML and JUnit logging. HTML provides the possibility to view the log in HTML while JUnit uses the logs in CI, correspondingly.
504
-
505
- Running of built-in HTML generators for RSpec and Cucumber logging is available if you run the tests using the `rake` tasks.
506
-
507
- **Example:**
508
-
509
- Running **_RSpec_** tests with the `rake` tasks.
510
-
511
- ```bash
512
- rake rspec: all
513
- ```
514
-
515
- **Example:**
516
-
517
- Running **_Cucumber_** tests with the `rake` tasks.
518
-
519
- ```bash
520
- rake cucumber: all
521
- ```
522
-
523
- It is also possible to manually run the tests with automatic logging.
524
-
525
- **Example:**
526
-
527
- To manually start a specific RSpec test:
528
-
529
- ```bash
530
- rspec spec/my_spec.rb -format html -out =./log/log.html
531
- ```
532
-
533
- To manually run an RSpec test:
534
-
535
- ```bash
536
- rspec -format html -out =./log/log.html
537
- ```
538
-
539
- To manually start a certain _feature_:
540
-
541
- ```bash
542
- cucumber features/first.feature -format html -out =./log/log.html
543
- ```
544
-
545
- To manually start all _features_:
546
-
547
- ```bash
548
- cucumber -format html -out =./log/log.html
549
- ```
550
-
551
- ### Extended Logging ###
552
-
553
- The Extended logging in a text file and in the console is also available.
554
- It uses the _log manager_ provided by the **_log_** method.
555
-
556
- _Howitzer_ supports 4 levels of logging: _**FATAL, WARN, INFO, DEBUG.**_
557
-
558
- FATAL <WARN <INFO <DEBUG
559
-
560
- **Example:**
561
-
562
- ```bash
563
- log.info "info message"
564
- ```
565
-
566
- To create a record with a different level, use the appropriate method.
567
-
568
- **Example:**
569
-
570
- ```bash
571
- log.warn "warning message"
572
- log.fatal "fatal message"
573
- ```
574
-
575
- If the option `settings.debug_mode` = true, the logger will record messages with **DEBUG** status.
576
-
577
- Logs are generated and saved in the **log** _directory_.
578
-
579
- ```bash
580
- / log
581
- log.txt
582
- log.html
583
- TEST-(your-feature-name). Xml
584
- ```
585
-
586
- Examples of logs usage in **Pages** and **Email**.
587
-
588
- **Example:** with **Page.**
589
-
590
- ```ruby
591
- class MyPage < WebPage
592
- def submit_form
593
- log.info "[ACTION] Submit form"
594
-
595
- end
596
-
597
- def fill_form
598
- log.info "[ACTION] Fill form"
599
-
600
- end
601
- end
602
- ```
603
-
604
- **Example:** with **Email.**
605
-
606
- ```ruby
607
- class TestEmail < Email
608
- SUBJECT = "Test email"
609
-
610
- def addressed_to?(new_user)
611
- if /Hi #{ new_user }/ === plain_text_body
612
- log.info "some message"
613
- else
614
- log.warn "some mesage"
615
- end
616
- end
617
- end
618
- ```
619
-
620
- ## Data Generators ##
621
-
622
- The Data generator allows generating data structures (e.g. User) and store the data in its own Memory storage.
623
-
624
- ### Data Storage ##
625
-
626
- The Data Storage is a simple key value storage that uses namespaces (e.g. :user, :sauce, etc.).
627
-
628
- This module has next methods:
629
- The module supports the following methods:
630
-
631
- <table>
632
- <thead>
633
- <tr>
634
- <th align="center">Method</th>
635
- <th align="center">Description</th>
636
- </tr>
637
- </thead>
638
- <tbody>
639
- <tr>
640
- <td>DataStorage.store(ns,key,value) </td>
641
- <td>Adds data to the storage, where ns is a unique namespace name.</td>
642
- </tr>
643
- <tr>
644
- <td>DataStorage::extract(ns, key=nil)</td>
645
- <td>Gets data from the storage by a namespace and a key. If a key is not specified, it will return all data from the namespace.</td>
646
- </tr>
647
- <tr>
648
- <td>DataStorage::clear_ns(ns)</td>
649
- <td>Removes a namespace with the data.</td>
650
- </tr>
651
- <tr>
652
- <td>DataStorage::clear_all_ns(exception_list=SPECIAL_NS_LIST)</td>
653
- <td>Removes all namespaces except special namespaces provided as an array.</td>
654
- </tr>
655
- </tbody>
656
- </table>
657
-
658
- **Example:**
659
-
660
- ```ruby
661
- DataStorage.store(:user, 1, User.new('Peter'))
662
- DataStorage.store(:user, 2, User.new('Dan'))
663
- DataStorage.store(:post, "post1", Post.new("Amazing post"))
664
- ```
665
-
666
- In memory it looks like:
667
-
668
- ```ruby
669
- {
670
- user: {
671
- 1 => User.new('Peter'),
672
- 2 => User.new('Dan')
673
- },
674
- post: {
675
- "post1" => Post.new("Amazing post")
676
- }
677
- }
678
- ```
679
-
680
- ### Generator ####
681
-
682
- This module uses standard methods for generating test data.
683
- It has one standard data object for generation, because it is applicable to almost all tests:
684
-
685
- _DataGenerator::Gen::User._
686
-
687
- _DataGenerator::Gen::User_ has the params:
688
-
689
- :login, :domain, :email, :password, :mailbox, :first_name, :last_name, :full_name
690
-
691
- Use _Gen::user(params={})_ method to generate this object.
692
-
693
- Also you can reopen _Gen_ module to add your own objects for generation. You can use this module to generate some other data specific for your tests.
694
- When using Cucumber, create a Gen.rb file in the **/features/support** directory. When using Rspec, create a _Gen.rb_ file in the **/spec/support** directory.
695
-
696
- ### Cucumber Transformers ###
697
-
698
- In **/features/support/tranformers.rb** file are described Cucumber transformers (to see more info visit this one:
699
- You will find the description of the Cucumber transformers in the **/features/support/tranformers.rb** file. To get more information, refer to this site:
700
- [https://github.com/cucumber/cucumber/wiki/Step-Argument-Transforms](https://github.com/cucumber/cucumber/wiki/Step-Argument-Transforms)).
701
- We use transformers for generating data objects in tests. Let’s imagine, for example, that you need to write a _sign_up.feature:_
702
-
703
- ```ruby
704
- Feature: Sign Up
705
-
706
- In order to use all functionality of the system
707
- As unregistered user
708
- I want to register to the system
709
-
710
- Scenario: correct credentials
711
- Given Register page
712
- And new UNIQ_USER user # it’s generate User object with generated test data that are transformed in hash in _transformers.rb_ file.
713
- When I put next register data and apply it
714
-
715
- |username |email |password |
716
- |UNIQ_USER[:username]|UNIQ_USER[:email] |UNIQ_USER[:password]|
717
- ```
718
-
719
- The last line will automatically replace `UNIQ_USER[:username]` for generated data which you can use.
720
-
721
- You can write your own transformers for other generated objects (that you will create in the DataGenerator::Gen module).
722
-
723
-
724
- ## Structure of RSpec Folder ##
725
-
726
- The **/spec** folder contains all supporting .rspec code and tests.
727
- All .rspec settings are located in the **spec_helper.rb** file. You can edit the .rspec settings as you want.
728
-
729
- The **/spec/support** file contains a help code, e.g. the code that generates test data.
730
- It’s better to you modules here in every created files. Methods from this folder will be accessible in every **_spec.rb** file
731
- and every **_page.rb** file.
732
-
733
- It is important to keep all **_spec.rb** files in the folder that contains tests priority meaning in its name.
734
- You must create folders in the **/spec** in order to add the tests with the required priority level, then edit the constant **TEST_TYPES** in the **/tasks/rspec.rake** file to add a name of the folder you created as a symbol in the list.
735
-
736
- To run tests by a priority level, use the **Rake** tasks in the **/tasks/rspec.rake** file.
737
- The **TEST_TYPES = [:all, :health, :bvt, :p1]** constant has a list of all available test priorities as standard settings.
738
- To run all tests in the **/spec** folder, type in:
739
-
740
- ```bash
741
- rake rspec:all
742
- ```
743
-
744
- (:all will run all tests in the **/spec** folder). For example, to run :bvt tests you need to create a **/spec/bvt** folder and add some **_spec.rb** files there, then run a Rake task by:
745
-
746
- ```bash
747
- rake rspec:bvt
748
- ```
749
-
750
- To run tests with less priority level, use _:p1_:
751
-
752
- ```bash
753
- rake rspec:p1
754
- ```
755
-
756
- Also there is a standard option to run _Smoke_ tests:
757
-
758
- ```bash
759
- rake rspec:health
760
- ```
761
-
762
- In every directory that is in **/spec** folder, the name of is represents priority of tests that are in it,
763
- you can create subfolders that represents the business areas of tests. There is a constant in the **/tasks/rspec.rake**:
764
-
765
- **TEST_AREAS = []**
766
-
767
- Here you can add business areas of the created tests that are in subfolders. The names should be equal, e.g.:
768
- If *TEST_AREAS = [:accounts]*. There is a folder with the specs: **/spec/bvt/accounts.**
769
- You can run all tests from this folder using the command:
770
-
771
- ```bash
772
- rake rspec:bvt:accounts
773
- ```
774
-