howitzer 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +3 -1
- data/.ruby-gemset +1 -0
- data/.travis.yml +4 -1
- data/.yardopts +5 -0
- data/CHANGELOG.md +23 -1
- data/CONTRIBUTING.md +14 -0
- data/GETTING_STARTED.md +283 -183
- data/Gemfile +3 -2
- data/LICENSE +1 -1
- data/README.md +93 -39
- data/Rakefile +4 -0
- data/bin/howitzer +34 -5
- data/features/cli_help.feature +3 -2
- data/features/cli_new.feature +1 -1
- data/features/cli_unknown.feature +1 -1
- data/features/cli_update.feature +84 -0
- data/features/step_definitions/common_steps.rb +9 -1
- data/generators/base_generator.rb +30 -15
- data/generators/config/config_generator.rb +7 -7
- data/generators/config/templates/custom.yml +1 -0
- data/generators/config/templates/default.yml +35 -5
- data/generators/cucumber/templates/env.rb +2 -2
- data/generators/cucumber/templates/transformers.rb +3 -1
- data/generators/root/templates/Gemfile +5 -3
- data/generators/root/templates/Rakefile +2 -0
- data/generators/rspec/templates/example_spec.rb +3 -3
- data/generators/rspec/templates/spec_helper.rb +6 -7
- data/howitzer.gemspec +15 -15
- data/lib/howitzer/capybara/settings.rb +125 -49
- data/lib/howitzer/helpers.rb +161 -94
- data/lib/howitzer/mailgun/client.rb +1 -1
- data/lib/howitzer/tasks/framework.rake +3 -0
- data/lib/howitzer/utils.rb +1 -1
- data/lib/howitzer/utils/locator_store.rb +1 -1
- data/lib/howitzer/utils/log.rb +1 -1
- data/lib/howitzer/utils/page_validator.rb +1 -1
- data/lib/howitzer/version.rb +1 -1
- data/lib/howitzer/web_page.rb +11 -11
- data/spec/spec_helper.rb +25 -22
- data/spec/support/generator_helper.rb +8 -1
- data/spec/unit/generators/base_generator_spec.rb +242 -0
- data/spec/unit/generators/config_generator_spec.rb +34 -0
- data/spec/unit/generators/cucumber_generator_spec.rb +45 -0
- data/spec/unit/generators/emails_generator_spec.rb +31 -0
- data/spec/unit/generators/pages_generator_spec.rb +33 -0
- data/spec/unit/generators/root_generator_spec.rb +35 -0
- data/spec/unit/generators/rspec_generator_spec.rb +36 -0
- data/spec/unit/generators/tasks_generator_spec.rb +31 -0
- data/spec/unit/lib/capybara/dsl_ex_spec.rb +11 -11
- data/spec/unit/lib/capybara/settings_spec.rb +336 -58
- data/spec/unit/lib/email_spec.rb +17 -17
- data/spec/unit/lib/helpers_spec.rb +699 -315
- data/spec/unit/lib/mailgun/client_spec.rb +9 -9
- data/spec/unit/lib/mailgun/connector_spec.rb +20 -20
- data/spec/unit/lib/mailgun/response_spec.rb +9 -9
- data/spec/unit/lib/settings_spec.rb +6 -6
- data/spec/unit/lib/utils/data_generator/data_storage_spec.rb +31 -31
- data/spec/unit/lib/utils/data_generator/gen_spec.rb +20 -20
- data/spec/unit/lib/utils/locator_store_spec.rb +39 -39
- data/spec/unit/lib/utils/log_spec.rb +42 -42
- data/spec/unit/lib/utils/page_validator_spec.rb +69 -70
- data/spec/unit/lib/web_page_spec.rb +91 -69
- data/spec/unit/version_spec.rb +3 -3
- metadata +100 -78
- data/spec/unit/generators/generators_spec.rb +0 -175
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a374cf3c69c1e057678dfed76d2a45df4fe72091
|
4
|
+
data.tar.gz: 57021f22549c5393fb74e74e25bf26a24454d54a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39064d9e1cc0c11e8134c8a30cc99ae5d3053c4f2a5ae2be5eed12afc5b95882a560ee43fbeb0000297f8c8470837b11121205b459aedffeb612c60f5ccefcbf
|
7
|
+
data.tar.gz: 6fc24bf0d0e100eaad09e3965a291ab0e12b0a39cf47d7b4284f443d5cdfc8975bc985dd2e660471db39b6e542116874e11d9d7ce41c1e097f0eddde9bae99b3
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
CHANGED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
howitzer
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,31 @@
|
|
1
|
-
## [In git](https://github.com/strongqa/howitzer/compare/master
|
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
|
data/CONTRIBUTING.md
ADDED
@@ -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.
|
data/GETTING_STARTED.md
CHANGED
@@ -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**
|
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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
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="
|
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="
|
40
|
+
<td align="center">
|
55
41
|
Boolean <br/><br/>
|
56
42
|
Boolean
|
57
43
|
</td>
|
58
|
-
<td align="
|
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
|
-
|
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"
|
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">
|
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
|
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
|
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
|
-
|
142
|
+
It means that each page is inherited from a parent class 'Web Page' which contains common methods for all pages.
|
154
143
|
|
155
|
-
|
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
|
-
|
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
|
178
|
-
|
164
|
+
Howitzer provides 3 different validation types:
|
179
165
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
294
|
-
[[Back To Top]](#jump-to-section)
|
343
|
+
### Good Practices Rules ###
|
295
344
|
|
345
|
+
Good Practice Rules
|
296
346
|
|
297
|
-
**
|
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
|
-
|
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
|
-
|
374
|
+
# ...
|
375
|
+
MyPage.given
|
323
376
|
end
|
324
377
|
end
|
325
378
|
```
|
326
379
|
|
327
|
-
**
|
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
|
-
|
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
|
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
|
432
|
+
You can use a **free** account. Follow the below steps to create an account:
|
376
433
|
|
377
|
-
1.
|
378
|
-
2.
|
379
|
-
3.
|
380
|
-
4.
|
381
|
-
5.
|
382
|
-
6.
|
383
|
-
7.
|
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
|
-
|
386
|
-
|
387
|
-
|
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)** -
|
392
|
-
* **.find (recipient, subject)** - same as the **self.find_by_recipient (recipient)
|
393
|
-
* **\#plain_text_body** - receiving body of
|
394
|
-
* **\#html_body** - receiving body of messages
|
395
|
-
* **\#text_body** - receiving body of messages as stripped text
|
396
|
-
* **\#mail_from** - returns
|
397
|
-
* **\#recipients** - returns array of recipients who
|
398
|
-
* **\#received_time** - returns email received
|
399
|
-
* **\#sender_email** - returns
|
400
|
-
* **\#get_mime_part** - allows you
|
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
|
-
|
482
|
+
This is how a custom class might look like:
|
483
|
+
|
410
484
|
```ruby
|
411
|
-
#
|
485
|
+
#put the class to ./emails/my_email.rb file
|
412
486
|
|
413
|
-
class MyEmail <Email
|
414
|
-
|
487
|
+
class MyEmail <Email
|
488
|
+
SUBJECT = "Test email" # specify the subject of an email
|
415
489
|
|
416
|
-
|
417
|
-
|
418
|
-
|
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
|
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
|
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
|
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
|
517
|
+
Running **_Cucumber_** tests with the `rake` tasks.
|
518
|
+
|
445
519
|
```bash
|
446
520
|
rake cucumber: all
|
447
521
|
```
|
448
522
|
|
449
|
-
|
523
|
+
It is also possible to manually run the tests with automatic logging.
|
450
524
|
|
451
525
|
**Example:**
|
452
526
|
|
453
|
-
|
527
|
+
To manually start a specific RSpec test:
|
528
|
+
|
454
529
|
```bash
|
455
|
-
rspec spec
|
530
|
+
rspec spec/my_spec.rb -format html -out =./log/log.html
|
456
531
|
```
|
457
532
|
|
458
|
-
|
533
|
+
To manually run an RSpec test:
|
534
|
+
|
459
535
|
```bash
|
460
|
-
rspec -
|
536
|
+
rspec -format html -out =./log/log.html
|
461
537
|
```
|
462
538
|
|
463
|
-
|
539
|
+
To manually start a certain _feature_:
|
540
|
+
|
464
541
|
```bash
|
465
|
-
cucumber features
|
542
|
+
cucumber features/first.feature -format html -out =./log/log.html
|
466
543
|
```
|
467
|
-
|
544
|
+
|
545
|
+
To manually start all _features_:
|
546
|
+
|
468
547
|
```bash
|
469
|
-
cucumber -
|
548
|
+
cucumber -format html -out =./log/log.html
|
470
549
|
```
|
471
550
|
|
472
|
-
### Extended
|
473
|
-
[[Back To Top]](#jump-to-section)
|
551
|
+
### Extended Logging ###
|
474
552
|
|
475
|
-
Extended logging
|
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_
|
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
|
-
|
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
|
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
|
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
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
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
|
581
|
-
|
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
|
-
|
691
|
+
Use _Gen::user(params={})_ method to generate this object.
|
590
692
|
|
591
|
-
Also you can reopen _Gen_ module to add your own objects
|
592
|
-
|
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
|
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
|
616
|
-
|UNIQ_USER[:username]|UNIQ_USER[:email] |
|
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
|
-
|
621
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
635
|
-
You
|
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
|
639
|
-
**TEST_TYPES = [:all, :health, :bvt, :p1]** has a list of available
|
640
|
-
To run all tests in **/spec** folder
|
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
|
-
|
646
|
-
**/spec/bvt** folder and add some **_spec.rb** files there,
|
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
|
-
|
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.
|
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
|
-
|
668
|
-
If *TEST_AREAS = [:accounts]
|
669
|
-
You can run all tests from this folder
|
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
|