howitzer 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +3 -1
  4. data/.ruby-gemset +1 -0
  5. data/.travis.yml +4 -1
  6. data/.yardopts +5 -0
  7. data/CHANGELOG.md +23 -1
  8. data/CONTRIBUTING.md +14 -0
  9. data/GETTING_STARTED.md +283 -183
  10. data/Gemfile +3 -2
  11. data/LICENSE +1 -1
  12. data/README.md +93 -39
  13. data/Rakefile +4 -0
  14. data/bin/howitzer +34 -5
  15. data/features/cli_help.feature +3 -2
  16. data/features/cli_new.feature +1 -1
  17. data/features/cli_unknown.feature +1 -1
  18. data/features/cli_update.feature +84 -0
  19. data/features/step_definitions/common_steps.rb +9 -1
  20. data/generators/base_generator.rb +30 -15
  21. data/generators/config/config_generator.rb +7 -7
  22. data/generators/config/templates/custom.yml +1 -0
  23. data/generators/config/templates/default.yml +35 -5
  24. data/generators/cucumber/templates/env.rb +2 -2
  25. data/generators/cucumber/templates/transformers.rb +3 -1
  26. data/generators/root/templates/Gemfile +5 -3
  27. data/generators/root/templates/Rakefile +2 -0
  28. data/generators/rspec/templates/example_spec.rb +3 -3
  29. data/generators/rspec/templates/spec_helper.rb +6 -7
  30. data/howitzer.gemspec +15 -15
  31. data/lib/howitzer/capybara/settings.rb +125 -49
  32. data/lib/howitzer/helpers.rb +161 -94
  33. data/lib/howitzer/mailgun/client.rb +1 -1
  34. data/lib/howitzer/tasks/framework.rake +3 -0
  35. data/lib/howitzer/utils.rb +1 -1
  36. data/lib/howitzer/utils/locator_store.rb +1 -1
  37. data/lib/howitzer/utils/log.rb +1 -1
  38. data/lib/howitzer/utils/page_validator.rb +1 -1
  39. data/lib/howitzer/version.rb +1 -1
  40. data/lib/howitzer/web_page.rb +11 -11
  41. data/spec/spec_helper.rb +25 -22
  42. data/spec/support/generator_helper.rb +8 -1
  43. data/spec/unit/generators/base_generator_spec.rb +242 -0
  44. data/spec/unit/generators/config_generator_spec.rb +34 -0
  45. data/spec/unit/generators/cucumber_generator_spec.rb +45 -0
  46. data/spec/unit/generators/emails_generator_spec.rb +31 -0
  47. data/spec/unit/generators/pages_generator_spec.rb +33 -0
  48. data/spec/unit/generators/root_generator_spec.rb +35 -0
  49. data/spec/unit/generators/rspec_generator_spec.rb +36 -0
  50. data/spec/unit/generators/tasks_generator_spec.rb +31 -0
  51. data/spec/unit/lib/capybara/dsl_ex_spec.rb +11 -11
  52. data/spec/unit/lib/capybara/settings_spec.rb +336 -58
  53. data/spec/unit/lib/email_spec.rb +17 -17
  54. data/spec/unit/lib/helpers_spec.rb +699 -315
  55. data/spec/unit/lib/mailgun/client_spec.rb +9 -9
  56. data/spec/unit/lib/mailgun/connector_spec.rb +20 -20
  57. data/spec/unit/lib/mailgun/response_spec.rb +9 -9
  58. data/spec/unit/lib/settings_spec.rb +6 -6
  59. data/spec/unit/lib/utils/data_generator/data_storage_spec.rb +31 -31
  60. data/spec/unit/lib/utils/data_generator/gen_spec.rb +20 -20
  61. data/spec/unit/lib/utils/locator_store_spec.rb +39 -39
  62. data/spec/unit/lib/utils/log_spec.rb +42 -42
  63. data/spec/unit/lib/utils/page_validator_spec.rb +69 -70
  64. data/spec/unit/lib/web_page_spec.rb +91 -69
  65. data/spec/unit/version_spec.rb +3 -3
  66. metadata +100 -78
  67. data/spec/unit/generators/generators_spec.rb +0 -175
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ccf5128e9fd63e0b38181fb268f299e7fce85b5
4
- data.tar.gz: 7673a8839534fa1b4e66857b3c5ece195564637f
3
+ metadata.gz: a374cf3c69c1e057678dfed76d2a45df4fe72091
4
+ data.tar.gz: 57021f22549c5393fb74e74e25bf26a24454d54a
5
5
  SHA512:
6
- metadata.gz: 5a38c6ce3b3c19ddd8479290fc106fd248ea8746938fb8fd5efae051b5a3fe404007b41504f6d701b48d3ee44d1ca53a1326d7da4c220f62cd5d6753d95535c8
7
- data.tar.gz: f53c4432a9ebe7407ea49b53b978370b6d7bfa790ce3ebee55c3591897800156beaf3c810ed3a51817fd22087ce8998cbf3fc9a9f91cf88adeb1dcc4df426c6d
6
+ metadata.gz: 39064d9e1cc0c11e8134c8a30cc99ae5d3053c4f2a5ae2be5eed12afc5b95882a560ee43fbeb0000297f8c8470837b11121205b459aedffeb612c60f5ccefcbf
7
+ data.tar.gz: 6fc24bf0d0e100eaad09e3965a291ab0e12b0a39cf47d7b4284f443d5cdfc8975bc985dd2e660471db39b6e542116874e11d9d7ce41c1e097f0eddde9bae99b3
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore CHANGED
@@ -6,6 +6,8 @@ vendor/bundle/*
6
6
  spec/log/*
7
7
  Gemfile.lock
8
8
  doc
9
- tmp
9
+ .yardoc
10
+ tmp/*
10
11
  .bundle
11
12
  **/.DS_Store
13
+ .ruby-version
@@ -0,0 +1 @@
1
+ howitzer
@@ -2,4 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.1
5
+ - 2.1.6
6
+ - 2.2.0
7
+ - 2.2.1
8
+ - 2.2.2
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ -
3
+ GETTING_STARTED.md
4
+ CONTRIBUTING.md
5
+ LICENSE
@@ -1,9 +1,31 @@
1
- ## [In git](https://github.com/strongqa/howitzer/compare/master...develop)
1
+ ## [In git](https://github.com/strongqa/howitzer/compare/v1.1.0...master)
2
2
 
3
3
  ### New Features
4
4
 
5
5
  ### Bugfixes
6
6
 
7
+ ## [v1.1.0](https://github.com/strongqa/howitzer/compare/v1.0.2...v1.1.0)
8
+
9
+ ### New Features
10
+ - Simplified upgrading process(`howitzer update`)
11
+ - Added new Rubies supporting (2.1.4-2.2.2)
12
+ - Added Selenium Grid supporting
13
+ - Added Browserstack supporting
14
+ - Added windows maximization in tests
15
+ - Added Safari supporting
16
+ - Added general framework rake tasks
17
+ - Migrated to Cucumber 2.x
18
+ - Migrated to Rspec 3.x
19
+ - Actualized other dependencies
20
+ - Updated and extended documentation.
21
+ - Improved unit test coverage
22
+ - Added integration with [coveralls.io](https://coveralls.io/r/strongqa/howitzer)
23
+ - Integrated YardDoc
24
+ - Integrated Gitter
25
+
26
+ ### Bugfixes
27
+ - Fixed issue with loading ActiveSupport
28
+
7
29
  ## [v1.0.2](https://github.com/strongqa/howitzer/compare/v1.0.1...v1.0.2)
8
30
 
9
31
  ### New Features
@@ -0,0 +1,14 @@
1
+ # Contributing to Howitzer
2
+
3
+ We love pull requests from everyone.
4
+
5
+ To contribute to Howitzer:
6
+
7
+ 1. Fork the [official repository](https://github.com/strongqa/howitzer/tree/master).
8
+ 2. Make your changes in a topic branch.
9
+ 3. Send a pull request.
10
+
11
+ Notes:
12
+
13
+ * Contributions without tests won't be accepted.
14
+ * Please don't update the Gem version.
@@ -1,37 +1,20 @@
1
- Getting Started
1
+ Getting Started
2
2
  ===============
3
3
 
4
- ## Jump to Section
5
- * [Available Drivers](#available-drivers)
6
- * [Pages](#pages)
7
- * [Validations](#validations)
8
- * [Locators](#locators)
9
- * [Pages With Static Information](#pages-with-static-information)
10
- * [Redefining of the pen method](#redefining-of-the-open-method)
11
- * [Good Practices](#good-practices)
12
- * [Emails](#emails)
13
- * [Logging](#logging)
14
- * [BUILT-IN Logging](#built-in-logging)
15
- * [Extended Logging](#extended-logging)
16
- * [Data Generators](#data-generators)
17
- * [Data Storage](#data-storage)
18
- * [Generator](#generator)
19
- * [Cucumber Tranformers](#cucumber-transformers)
20
- * [RSpec Folder Structure](#rspec-folder-structure)
21
-
22
4
  Available Drivers
23
5
  ------
24
- [[Back To Top]](#jump-to-section)
25
6
 
26
- **Driver** - universal interface for test runners against to different web browsers. All implementations of drivers can be divided to 2 categories:
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).
27
11
 
28
- * **Headless testing** - browser emulation without GUI(very useful on CI servers, like Bamboo, TeamCity, Jenkins, etc.)
29
- * **Real browser testing** - integration with real browsers via extensions, plugins, ActiveX, etc.(for local and cloud based testing, like SauceLabs, Testingbot)
12
+ Howitzer uses [Capybara](http://jnicklas.github.io/capybara/) for the driver management and configuration. All you need to do is to:
30
13
 
31
- Howitzer uses [Capybara](http://jnicklas.github.io/capybara/) for driver management and configuration. All that you really need:
32
- - specify the **driver** settings in _config/default.yml_
33
- - specify some additional settings for chosen driver.
34
- Bellow you can find aggregated table with some useful informations about driver settings in Howitzer:
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:
35
18
 
36
19
  <table>
37
20
  <thead>
@@ -45,45 +28,52 @@ Bellow you can find aggregated table with some useful informations about driver
45
28
  </thead>
46
29
  <tbody>
47
30
  <tr>
48
- <td><a href="http://phantomjs.org/">phantomjs</a>(<strong>default</strong>)</td>
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>
49
35
  <td align="center">Headless</td>
50
- <td align="left" rowspan="2">
36
+ <td align="center">
51
37
  <strong>pjs_ignore_js_errors</strong><br/><br/>
52
38
  <strong>pjs_ignore_ssl_errors</strong>
53
39
  </td>
54
- <td align="left" rowspan="2">
40
+ <td align="center">
55
41
  Boolean <br/><br/>
56
42
  Boolean
57
43
  </td>
58
- <td align="left" rowspan="2">
44
+ <td align="center">
59
45
  if false, then raises exception on js error in app<br/>
60
- if false, then ignores ssl warnings
46
+ if false, then ignores ssl warnings<br/>
61
47
  </td>
62
48
  </tr>
63
- <tr>
64
- <td><a href="https://github.com/teampoltergeist/poltergeist">poltergeist</a></td>
65
- <td align="center">Headless</td>
66
- </tr>
49
+
67
50
  <tr>
68
51
  <td><a href="https://github.com/thoughtbot/capybara-webkit">webkit</a></td>
69
52
  <td align="center">Headless</td>
70
53
  <td align="center">-</td>
71
54
  <td align="center">-</td>
72
- <td align="center">-</td>
55
+ <td align="center">Uncomment `gem 'capybara-webkit'` in Gemfile</td>
73
56
  </tr>
74
57
  <tr>
75
58
  <td><a href="https://code.google.com/p/selenium/wiki/RubyBindings">selenium</a></td>
76
59
  <td align="center">Real</td>
77
60
  <td align="center"><strong>sel_browser</strong></td>
78
61
  <td align="center">String</td>
79
- <td align="center">specify one of next browsers: iexplore (ie), firefox (ff), chrome, opera, safari</td>
62
+ <td align="center">Indicate one of the following browsers: iexplore (ie), firefox (ff), chrome, opera, safari.</td>
80
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>
81
71
  <tr>
82
72
  <td>selenium_dev</td>
83
73
  <td align="center">Real</td>
84
74
  <td align="center"><strong>-</strong></td>
85
75
  <td align="center">-</td>
86
- <td align="center">Execute tests against to FireFox with firebug and firepath extensions</td>
76
+ <td align="center">Execute tests against FireFox (with Firebug and FirePath extensions).</td>
87
77
  </tr>
88
78
  <tr>
89
79
  <td><a href="https://saucelabs.com">sauce</a></td>
@@ -141,20 +131,19 @@ Bellow you can find aggregated table with some useful informations about driver
141
131
 
142
132
  Pages
143
133
  ------
144
- [[Back To Top]](#jump-to-section)
145
134
 
146
- Pages - are classes that’s describe real web pages. For example, 'Home page' can be described as:
135
+ Pages are classes describing real web pages. For example, 'Home page' can be described as:
147
136
 
148
137
  ```ruby
149
138
  class HomePage < WebPage
150
139
  end
151
140
  ```
152
141
 
153
- Thus, we realize that each page is inherited from a parent class 'Web Page', which contains the common methods for all pages.
142
+ It means that each page is inherited from a parent class 'Web Page' which contains common methods for all pages.
154
143
 
155
- Each page contains required constant URL(the relative URL of the page):
144
+ Every page contains a required constant URL (the relative URL of the page):
156
145
 
157
- **Example :**
146
+ **Example:**
158
147
 
159
148
  ```ruby
160
149
  # put the class to ./pages/home_page.rb file
@@ -165,23 +154,45 @@ end
165
154
  ```
166
155
 
167
156
  ### Validations
168
- [[Back To Top]](#jump-to-section)
169
157
 
170
- Pape Object pattern does not expect using any validations on UI driver level. But at the same time, each page must have
171
- some anchor in order to identify page exclusively.
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.
172
159
 
173
160
  ```ruby
174
161
  validates <type>, options
175
162
  ```
176
163
 
177
- Howitzer providers 3 different validation types:
178
-
164
+ Howitzer provides 3 different validation types:
179
165
 
180
- Validation Type | Options | Value Type | Description
181
- :-----------------:|:-------:|:-------------:|:-----------------------------------------:
182
- : url | pattern | Regexp | matches current url to pattern
183
- : title | pattern | Regexp | matches current pate title to pattern
184
- : element_presence | locator | String/Symbol | find element by locator on current page
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>
185
196
 
186
197
  **Example 1:**
187
198
 
@@ -213,7 +224,7 @@ class LoginPage < WebPage
213
224
  end
214
225
  ```
215
226
 
216
- Howitzer allows use all 3 validations, but only 1 is really required. If any validation is failed, exception will be raised.
227
+ Howitzer allows using all 3 validations, but only 1 is really required. If any validation fails, the exception will appear.
217
228
 
218
229
  **CAUTION:** Page validation is triggered in 2 cases only:
219
230
 
@@ -222,23 +233,47 @@ Howitzer allows use all 3 validations, but only 1 is really required. If any val
222
233
 
223
234
 
224
235
  ### Locators ###
225
- [[Back To Top]](#jump-to-section)
226
236
 
227
237
  Locator is a search item (selector) of one or more elements on a 'Web page'.
228
238
 
229
239
  The table below lists the types of locators, the possible methods of searching and Capybara methods, which may be called.
230
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>
231
272
 
232
- Locator Type | Search Methods | Capybara Methods
233
- :----------------:|:-----------------------:|:----------------------------:
234
- : locator | css(by default), path | find, all, first
235
- : link_locator | id, text | click_link, find_link
236
- : field_locator | id, name, text | find_field, fill_in
237
- : button_locator | id, name, text | click_button, find_button
238
-
239
- Each page contains a description of all elements by adding the appropriate locators that are preceded by the prefix **add_**
273
+ Each page contains a description of all elements by adding the appropriate locators that are preceded by the prefix **add\_**
240
274
 
241
275
  **Example:**
276
+
242
277
  ```ruby
243
278
  class HomePage < WebPage
244
279
  URL = '/'
@@ -257,12 +292,25 @@ class HomePage < WebPage
257
292
  end
258
293
  ```
259
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
+
260
308
  ### Pages with static information ###
261
- [[Back To Top]](#jump-to-section)
262
309
 
263
- In case of repeated static information in several different pages, it would be good decision to move up these methods into separate module.
310
+ If static information is repeated on several different pages, it can be a good idea to move these methods into a separate module.
264
311
 
265
312
  **Example:**
313
+
266
314
  ```ruby
267
315
  module TopMenu
268
316
  def self.included(base)
@@ -277,11 +325,13 @@ module TopMenu
277
325
  end
278
326
  end
279
327
  ```
280
- #### Redefining of the *open* method #####
328
+
329
+ ### Redefining of the *open* method #####
281
330
 
282
331
  It is used when you need to open a page with additional parameters.
283
332
 
284
333
  **Example:**
334
+
285
335
  ```ruby
286
336
  class MyPage < WebPage
287
337
  def self.open(url="#{app_url}#{self::URL}+'?no_popup=true'")
@@ -290,196 +340,225 @@ class MyPage < WebPage
290
340
  end
291
341
  ```
292
342
 
293
- ### Good practices ###
294
- [[Back To Top]](#jump-to-section)
343
+ ### Good Practices Rules ###
295
344
 
345
+ Good Practice Rules
296
346
 
297
- **First rule:** do not get tied to the interface. Thats means that the name and description of the methods you should use a common phrases.
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.
298
348
 
299
349
  **Example:**
350
+
300
351
  ```ruby
301
352
  class MyPage < WebPage
302
353
  def submit_form
303
-
354
+ # ...
304
355
  end
305
356
 
306
357
  def fill_form(value)
307
-
358
+ # ...
308
359
  end
309
360
  end
310
361
  ```
311
- **Second rule:** any ACTION methods should return an instance of the page.
312
- This allows you to do the following:
362
+
363
+ **Rule Two:** Any ACTION method should return an instance of the page. This allows you to do the following:
313
364
 
314
365
  ```ruby
315
366
  MyPage.open.fill_form.submit_form
316
367
  ```
368
+
317
369
  **Example:**
318
- ```
370
+
371
+ ```ruby
319
372
  class MyPage < WebPage
320
373
  def fill_form
321
- ..............
322
- MyPage.given
374
+ # ...
375
+ MyPage.given
323
376
  end
324
377
  end
325
378
  ```
326
379
 
327
- **Third rule:** coding of checks in the methods in the class pages are __prohibited.__
380
+ **Rule Three:** Coding of checks in the class pages methods are __prohibited.__
328
381
 
329
382
  **Example:**
383
+
330
384
  ```ruby
331
385
  class MyPage < WebPage
332
386
  def submit_form
333
- ….
387
+ # ...
334
388
  end
335
389
 
336
390
  def get_all_prices
337
-
391
+ # ...
338
392
  prices
339
393
  end
340
394
  end
341
395
  ```
396
+
342
397
  my_page_spec.rb
343
398
  ```ruby
344
399
  require 'spec_helper'
345
400
 
346
401
  describe “some feature” do
347
402
  context “when...” do
348
- it {expect(MyPage.get_all_prices).to include(400)}
403
+ it { expect(MyPage.get_all_prices).to include(400) }
349
404
  end
350
405
  end
351
406
  ```
352
- **Fourth rule:** all ACTION methods should create log entries
407
+
408
+ **Rule Four:** All ACTION methods should create log entries.
353
409
 
354
410
  **Example:**
411
+
355
412
  ```ruby
356
413
  class MyPage < WebPage
357
414
  def submit_form
358
415
  log.info { "[ACTION] Submit form" }
359
- ….
416
+ # ...
360
417
  end
361
418
 
362
419
  def fill_form
363
420
  log.info { "[ACTION] Fill form" }
364
-
421
+ # ...
365
422
  end
366
423
  end
367
424
  ```
368
425
 
369
426
  Emails
370
427
  ------
371
- [[Back To Top]](#jump-to-section)
372
428
 
373
- Howitzer uses amazing service [Mailgun](http://mailgun.com) which allows to catch all emails of sandbox domain, and to store them to its data storage during 3 days. It is extrimaly useful for new user creation with email confirmation during testing of web applications
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.
374
431
 
375
- You can use **free** account. Follow steps below:
432
+ You can use a **free** account. Follow the below steps to create an account:
376
433
 
377
- 1. Sign up [here](https://mailgun.com/signup)
378
- 2. Login and copy your API Key
379
- 3. Open config/default.yml file of your project, find **mailgun_key** setting and past copied api key there.
380
- 4. Open Mailgun web page again and copy mailgun domain, ie. 'sandboxbaf443d4c81b43d0b64a413805dc6f68.mailgun.org'
381
- 5. Open config/default.yml file of your project again, find **mailgun_domain** setting and past copied mailgun domain there.
382
- 6. Open Mailgun web page again and navigate to **Routes** menu
383
- 7. Create new route with following parameters
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:
384
441
 
385
- Priority | Filter Expression | Action | Description
386
- :--------:|:---------------------:|:-------:|:------------------
387
- 0 | match_recipient(".*") | store() | Store all messages
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>
388
460
 
389
461
  _**Email**_ Class corresponds to one letter. Used to test the notifications.
390
462
 
391
- * **.find_by_recipient (recipient)** - search for the letter recipient. The parameter receives email recipient.
392
- * **.find (recipient, subject)** - same as the **self.find_by_recipient (recipient)**, but only in case, when we do not know in advance what kind of _subject_ has email.
393
- * **\#plain_text_body** - receiving body of message as plain text
394
- * **\#html_body** - receiving body of messages as html
395
- * **\#text_body** - receiving body of messages as stripped text
396
- * **\#mail_from** - returns who has send email data in format: User Name <user@email>
397
- * **\#recipients** - returns array of recipients who has received current email
398
- * **\#received_time** - returns email received time
399
- * **\#sender_email** - returns sender user email
400
- * **\#get_mime_part** - allows you to receive the attachment of email
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.
401
473
 
402
474
  **Example:**
475
+
403
476
  ```ruby
404
477
  class MyEmail < Email
405
478
  SUBJECT = 'TEST SUBJECT' # specify the subject of an email
406
479
  end
407
480
  ```
408
481
 
409
- Example, how custom class might look like:
482
+ This is how a custom class might look like:
483
+
410
484
  ```ruby
411
- # put the class to ./emails/my_email.rb file
485
+ #put the class to ./emails/my_email.rb file
412
486
 
413
- class MyEmail <Email
414
- SUBJECT = "Test email" # specify the subject of an email
487
+ class MyEmail <Email
488
+ SUBJECT = "Test email" # specify the subject of an email
415
489
 
416
- def addressed_to? (new_user) # check that the letter were sent to proper recipient
417
- / Hi # {new_user} / === plain_text_body
418
- end
419
- end
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
420
494
  ```
421
495
 
422
496
  Logging
423
497
  -------
424
- [[Back To Top]](#jump-to-section)
425
498
 
426
499
  *Howitzer* allows logging to the text file, HTML and output to the console.
427
500
 
428
501
  ### BUILT-IN logging ###
429
502
 
430
- *Howitzer* uses the opportunity of Cucumber and RSpec generate HTML, JUnit logging. HTML provide ability to view the log in HTML, JUnit - use the logs in CI, accordingly.
431
-
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.
432
504
 
433
- Running of an built-in HTML generators for RSpec and Cucumber logging, is available if you run the tests using a `rake` tasks.
505
+ Running of built-in HTML generators for RSpec and Cucumber logging is available if you run the tests using the `rake` tasks.
434
506
 
435
507
  **Example:**
436
508
 
437
- Running **_RSpec_** tests through `rake` tasks.
509
+ Running **_RSpec_** tests with the `rake` tasks.
510
+
438
511
  ```bash
439
512
  rake rspec: all
440
513
  ```
441
514
 
442
515
  **Example:**
443
516
 
444
- Running **_Cucumber_** tests through `rake` tasks.
517
+ Running **_Cucumber_** tests with the `rake` tasks.
518
+
445
519
  ```bash
446
520
  rake cucumber: all
447
521
  ```
448
522
 
449
- Manually running of the tests with automatic logging is also possible.
523
+ It is also possible to manually run the tests with automatic logging.
450
524
 
451
525
  **Example:**
452
526
 
453
- Manual start of some specific RSpec tests:
527
+ To manually start a specific RSpec test:
528
+
454
529
  ```bash
455
- rspec spec / my_spec.rb - format html-out =. / log / log.html
530
+ rspec spec/my_spec.rb -format html -out =./log/log.html
456
531
  ```
457
532
 
458
- Running RSpec tests manually:
533
+ To manually run an RSpec test:
534
+
459
535
  ```bash
460
- rspec - format html-out =. / log / log.html
536
+ rspec -format html -out =./log/log.html
461
537
  ```
462
538
 
463
- Manual start of certain _feature_:
539
+ To manually start a certain _feature_:
540
+
464
541
  ```bash
465
- cucumber features / first.feature - format html-out =. / log / log.html
542
+ cucumber features/first.feature -format html -out =./log/log.html
466
543
  ```
467
- Manual start all _features_:
544
+
545
+ To manually start all _features_:
546
+
468
547
  ```bash
469
- cucumber - format html - out =. / log / log.html
548
+ cucumber -format html -out =./log/log.html
470
549
  ```
471
550
 
472
- ### Extended logging ###
473
- [[Back To Top]](#jump-to-section)
551
+ ### Extended Logging ###
474
552
 
475
- Extended logging to a text file and to the console also available.
476
- It uses the _log manager_ provided by **_log_** method.
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.
477
555
 
478
- _Howitzer_ has 4 levels of logging: _**FATAL, WARN, INFO, DEBUG.**_
556
+ _Howitzer_ supports 4 levels of logging: _**FATAL, WARN, INFO, DEBUG.**_
479
557
 
480
558
  FATAL <WARN <INFO <DEBUG
481
559
 
482
560
  **Example:**
561
+
483
562
  ```bash
484
563
  log.info "info message"
485
564
  ```
@@ -487,21 +566,24 @@ log.info "info message"
487
566
  To create a record with a different level, use the appropriate method.
488
567
 
489
568
  **Example:**
569
+
490
570
  ```bash
491
571
  log.warn "warning message"
492
572
  log.fatal "fatal message"
493
573
  ```
494
574
 
495
- If the option `settings.debug_mode` = true, logger will record messages with **DEBUG** status.
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_.
496
578
 
497
- Logs are generated in the **log** _directory_ .
498
579
  ```bash
499
580
  / log
500
581
  log.txt
501
582
  log.html
502
583
  TEST-(your-feature-name). Xml
503
584
  ```
504
- Examples of using logs in **Pages** and **Email**.
585
+
586
+ Examples of logs usage in **Pages** and **Email**.
505
587
 
506
588
  **Example:** with **Page.**
507
589
 
@@ -520,12 +602,13 @@ end
520
602
  ```
521
603
 
522
604
  **Example:** with **Email.**
605
+
523
606
  ```ruby
524
607
  class TestEmail < Email
525
608
  SUBJECT = "Test email"
526
609
 
527
610
  def addressed_to?(new_user)
528
- if /Hi #{new_user}/ === plain_text_body
611
+ if /Hi #{ new_user }/ === plain_text_body
529
612
  log.info "some message"
530
613
  else
531
614
  log.warn "some mesage"
@@ -535,25 +618,45 @@ end
535
618
  ```
536
619
 
537
620
  ## Data Generators ##
538
- [[Back To Top]](#jump-to-section)
539
621
 
540
- Data generator allows to generate some data structures like User and store it to own Memory storage
622
+ The Data generator allows generating data structures (e.g. User) and store the data in its own Memory storage.
541
623
 
542
- ### Data Storage ###
624
+ ### Data Storage ##
543
625
 
544
- Data Storage is simple key value storage, which uses namespaces (for example, :user, :sauce, etc).
626
+ The Data Storage is a simple key value storage that uses namespaces (e.g. :user, :sauce, etc.).
545
627
 
546
628
  This module has next methods:
629
+ The module supports the following methods:
547
630
 
548
-
549
- Method | Description
550
- :------------------------------------------:|:--------------------------------------------------:
551
- | DataStorage.store(ns,key,value) | Adds data to storage, where ns - uniq namespace name
552
- | DataStorage::extract(ns, key=nil) | Gets data from storage by namespace and key. If key is not specified, then it will returns all data from namespace
553
- | DataStorage::clear_ns(ns) | Removes namespace with data
554
- | DataStorage::clear_all_ns(exception_list=SPECIAL_NS_LIST)| Removes all namespaces except special namespaces provided as array
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>
555
657
 
556
658
  **Example:**
659
+
557
660
  ```ruby
558
661
  DataStorage.store(:user, 1, User.new('Peter'))
559
662
  DataStorage.store(:user, 2, User.new('Dan'))
@@ -575,10 +678,9 @@ In memory it looks like:
575
678
  ```
576
679
 
577
680
  ### Generator ####
578
- [[Back To Top]](#jump-to-section)
579
681
 
580
- This module has standard methods for generate test data. It has one standard data object for generate, because this is
581
- more common for almost all tests:
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:
582
684
 
583
685
  _DataGenerator::Gen::User._
584
686
 
@@ -586,19 +688,17 @@ _DataGenerator::Gen::User_ has the params:
586
688
 
587
689
  :login, :domain, :email, :password, :mailbox, :first_name, :last_name, :full_name
588
690
 
589
- To generate this object use _Gen::user(params={})_ method.
691
+ Use _Gen::user(params={})_ method to generate this object.
590
692
 
591
- Also you can reopen _Gen_ module to add your own objects to generate, also use this module to generate some other data
592
- specific for your tests.
593
- When using Cucumber create Gen.rb file in **/features/support** directory. When using Rspec create
594
- _Gen.rb_ file in **/spec/support** directory.
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.
595
695
 
596
696
  ### Cucumber Transformers ###
597
697
 
598
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:
599
700
  [https://github.com/cucumber/cucumber/wiki/Step-Argument-Transforms](https://github.com/cucumber/cucumber/wiki/Step-Argument-Transforms)).
600
- We are using transformers to use generated data objects in tests. For example let’s imagine that we need to
601
- write _sign_up.feature:_
701
+ We use transformers for generating data objects in tests. Let’s imagine, for example, that you need to write a _sign_up.feature:_
602
702
 
603
703
  ```ruby
604
704
  Feature: Sign Up
@@ -612,43 +712,42 @@ Given Register page
612
712
  And new UNIQ_USER user # it’s generate User object with generated test data that are transformed in hash in _transformers.rb_ file.
613
713
  When I put next register data and apply it
614
714
 
615
- |username |email |password |
616
- |UNIQ_USER[:username]|UNIQ_USER[:email] | UNIQ_USER[:password]|
715
+ |username |email |password |
716
+ |UNIQ_USER[:username]|UNIQ_USER[:email] |UNIQ_USER[:password]|
617
717
  ```
618
- Last line will automatically replace UNIQ_USER[:username] for generated data, which you can use.
619
718
 
620
- You can wright your own transformers for some other generated objects, that you will generate
621
- in _DataGenerator::Gen_ module.
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).
622
722
 
623
723
 
624
- ## RSpec Folder Structure ##
625
- [[Back To Top]](#jump-to-section)
724
+ ## Structure of RSpec Folder ##
626
725
 
627
- **/spec** folder contains all supporting .rspec code and tests.
628
- There is **spec_helper.rb** file where all .rspec settings are. You could edit this .rspec settings for your purposes.
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.
629
728
 
630
- **/spec/support** contains helpers code, for example code that generates test data.
729
+ The **/spec/support** file contains a help code, e.g. the code that generates test data.
631
730
  It’s better to you modules here in every created files. Methods from this folder will be accessible in every **_spec.rb** file
632
731
  and every **_page.rb** file.
633
732
 
634
- All **_spec.rb** files should contains in folder that has tests priority meaning in it’s name.
635
- You should create folders in **/spec** to add there tests with needed priority level and edit constant **TEST_TYPES**
636
- in **/tasks/rspec.rake** file to add a name of create folder as symbol in list.
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.
637
735
 
638
- To run tests by priority level user **Rake** tasks in **/tasks/rspec.rake** file. Constant
639
- **TEST_TYPES = [:all, :health, :bvt, :p1]** has a list of available tests priorities as a standard settings.
640
- To run all tests in **/spec** folder use this:
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:
641
739
 
642
740
  ```bash
643
741
  rake rspec:all
644
742
  ```
645
- (_:all_ will run all tests in **/spec** folder). For example, to run _:bvt_ tests you need to create
646
- **/spec/bvt** folder and add some **_spec.rb** files there, than run Rake task by:
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:
647
745
 
648
746
  ```bash
649
747
  rake rspec:bvt
650
748
  ```
651
- For running tests with less priority level use _:p1_:
749
+
750
+ To run tests with less priority level, use _:p1_:
652
751
 
653
752
  ```bash
654
753
  rake rspec:p1
@@ -659,14 +758,15 @@ Also there is a standard option to run _Smoke_ tests:
659
758
  ```bash
660
759
  rake rspec:health
661
760
  ```
761
+
662
762
  In every directory that is in **/spec** folder, the name of is represents priority of tests that are in it,
663
- you can create subfolders that represents the business areas of tests. In **/tasks/rspec.rake** there is a constant:
763
+ you can create subfolders that represents the business areas of tests. There is a constant in the **/tasks/rspec.rake**:
664
764
 
665
765
  **TEST_AREAS = []**
666
766
 
667
- You can add here business areas of created tests that are in subfolders, names should be equal, for example:
668
- If *TEST_AREAS = [:accounts]* and there is a folder with specs in it: **/spec/bvt/accounts.**
669
- You can run all tests from this folder by command:
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:
670
770
 
671
771
  ```bash
672
772
  rake rspec:bvt:accounts