ATDD BY Example With Cucumber
-
Upload
doug-morgan -
Category
Technology
-
view
281 -
download
0
Transcript of ATDD BY Example With Cucumber
![Page 1: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/1.jpg)
A C C E P TA N C E T E S T D R I V E N D E V E L O P M E N TB Y E X A M P L E W I T H C U C U M B E R
![Page 2: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/2.jpg)
W H O W E A R E .
![Page 3: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/3.jpg)
@ D O U G M O R G A N _G I T H U B . C O M / D M O R G A N 3 4 0 5D O U G M O R G A N
![Page 5: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/5.jpg)
W O R K I N G A G R E E M E N T S
• Help each other out. • You aren't done until the person next to you is done.
• Time boxed breaks. • Respect your peers; please don't be late.
• Ask questions. • Speak up if you don't understand something.
![Page 6: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/6.jpg)
M O R N I N G A G E N D A
• Acceptance Test Driven Development • Why? • What?
• Shared Understanding/ Collaboration • Three Amigos • Acceptance Criteria • Gherkin • Cucumber
![Page 7: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/7.jpg)
A F T E R N O O N A G E N D A
• PageObject • Interacting with a web browser • Cleaner scenarios • Asserting requirements
• Q & A
![Page 8: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/8.jpg)
W H Y AT D D ?F I R S T O F F.
![Page 9: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/9.jpg)
W H Y AT D D ?
T >
^
F
X
![Page 10: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/10.jpg)
W H Y AT D D ?
• Clear definition of done • Over building. • Under building.
• Avoiding Rework • Due to not understanding requirements.
• Avoid Context Switching
![Page 11: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/11.jpg)
R E D U C E W A S T E .B A S I C A L LY.
![Page 12: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/12.jpg)
W H AT I S AT D D ?
![Page 13: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/13.jpg)
Acceptance Test Driven Development
![Page 14: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/14.jpg)
– M E R R I A M - W E B S T E R D I C T I O N A R Y
“The quality or state of being accepted or acceptable”
![Page 15: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/15.jpg)
Copyright LeanDog, Inc. All Rights Reserved. Do not copy or distribute without permission.
Ready Development Test Review Done
Product Owner
Developer Tester
![Page 16: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/16.jpg)
Copyright LeanDog, Inc. All Rights Reserved. Do not copy or distribute without permission.
Ready Development Test Review Done
Product Owner
Developer Tester
Meeting
?Done
TrackingPriority
Not
Done Done
UX
DoneNot
DoneNot
Done
![Page 17: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/17.jpg)
W A S T E .R E W O R K R E S U LT S I N
![Page 18: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/18.jpg)
S H A R E D U N D E R S TA N D I N G
DeveloperProduct Owner
Tester
M U LT I P L E P E R S P E C T I V E S
![Page 19: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/19.jpg)
S H A R E D U N D E R S TA N D I N G
Written words are the second worst form of
communication
![Page 20: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/20.jpg)
S H A R E D U N D E R S TA N D I N G
3030
1. 2.
3. 4.
"I'm glad we all agree"
"Ah!" "I'm glad we're all agreed then"
"Ah!"
"Crystal Clear: A Human-Powered Methodology for small teams" By Alistair Cockburn
Information Radiators Invented around the year 2000 by Alistair Cockburn
Clear Communication
*The Agile Samurai - Jonathan Rasmusson
![Page 21: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/21.jpg)
S H A R E D U N D E R S TA N D I N G
DeveloperProduct Owner
Tester
¡Arriba!
T H E “ T H R E E A M I G O S ”
![Page 22: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/22.jpg)
G H E R K I N S Y N TA X
Feature: …
Scenario: … Given … When … And … Then …
S H A R E D U N D E R S TA N D I N G
![Page 23: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/23.jpg)
S H A R E D U N D E R S TA N D I N G
![Page 24: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/24.jpg)
S H A R E D U N D E R S TA N D I N G
As a credit card paying customer,
I want to be informed when the credit card
information I have entered is in an invalid format.
So that I can correct my information and successfully complete
my transaction.
![Page 25: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/25.jpg)
S H A R E D U N D E R S TA N D I N G
Feature: Entering credit card information
Scenario: Credit card number too short
Scenario: Expiration date invalid
![Page 26: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/26.jpg)
S H A R E D U N D E R S TA N D I N G
Scenario: Credit card number too short Given I have chosen some items to buy And I am about to enter my credit card details When I enter a card number that's only 15 digits long Then I expect the page to be redisplayed And I expect to see “Credit card must be at least 16 digits”
![Page 27: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/27.jpg)
S H A R E D U N D E R S TA N D I N G
Scenario: Expiration date invalid Given I have chosen some items to buy And I am about to enter my credit card details When I enter a card expiration date that's in the past Then I expect the page to be redisplayed And I expect to see “Incorrect expiration date”
![Page 28: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/28.jpg)
brushtoothpaste
bristles water
![Page 29: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/29.jpg)
![Page 30: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/30.jpg)
Varieties of Language in Cucumber Scenarios
![Page 31: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/31.jpg)
TA U T O L O G I C A L
Scenario: Search for a Book When I search for a book Then I should see the correct results
![Page 32: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/32.jpg)
S U P E R T E C H N I C A L
Scenario: Search for a book Given the following Authors: | id | name | | 1 | Charles Dickens | | 2 | John Steinbeck | | 3 | Fyodor Dostoyevsky | And the following Titles: | id | title | author_id | | 1 | A Tale of Two Cities | 1 | | 2 | Crime and Punishment | 3 | | 3 | East of Eden | 2 | And I'm on "http://www.bookstore.biz/" When I fill in "Dickens" in "//input[name()='q']" And I click "#searchButton" Then there should be 1 "div.book div.title" element And the page should contain "A Tale of Two Cities"
![Page 33: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/33.jpg)
S C R I P T Y, W I T H I M P L E M E N TAT I O N D E TA I L S
Scenario: Search for a book Given the following catalog: | Title | Author | | A Tale of Two Cities | Charles Dickens | | Crime and Punishment | Fyodor Dostoyevsky | | East of Eden | John Steinbeck | And I'm on the bookstore home page When I fill in "Dickens" in the search field And I click "Search" Then I should see only "A Tale of Two Cities" in the results
![Page 34: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/34.jpg)
E X A M P L E I N D O M A I N L A N G U A G E
Scenario: Search for a book Given the following catalog: | Title | Author | | A Tale of Two Cities | Charles Dickens | | Crime and Punishment | Fyodor Dostoyevsky | | East of Eden | John Steinbeck | When I search for "Dickens" Then I should see only "A Tale of Two Cities" in the results
![Page 35: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/35.jpg)
E X A M P L E I N D O M A I N L A N G U A G E W I T H E X C E S S D E TA I L
Scenario: Search for a book Given the following catalog: | Title | Author | Publisher | ISBN | | A Tale of Two Cities | Charles Dickens | Qualitas Classics| 1897093594 | | Crime and Punishment | Fyodor Dostoyevsky| Simon & Brown | 1936041030 | | East of Eden | John Steinbeck | Penguin | 0142000655 | When I search for "Dickens" Then I should see only the following in the results: | Title | Author | Format | Price | | A Tale of Two Cities | Charles Dickens | Paperback | $14.90 |
![Page 36: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/36.jpg)
D I F F E R E N T K I N D S O F S C E N A R I O STa
utolog
iDom
ain La
ngua
ge
Domain
Lang
uage
Im
plemen
tation
Sup
er
Sweet
![Page 37: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/37.jpg)
E X E R C I S E
Identify different kinds of scenarios
![Page 38: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/38.jpg)
Acceptance Test Driven Development
![Page 39: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/39.jpg)
W H E N S H O U L D W E T E S T O U R C O D E ?
TestCode
Code TestMonths
Code TestWeeks
Code TestDays
![Page 40: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/40.jpg)
W H E N S H O U L D W E T E S T O U R C O D E ?
S T O R Y T W O
Code TestS T O R Y O N E
S T O R Y T W O
S T O R Y T W OContext Switching
S T O R Y O N E
R E W O R K
S T O R Y O N E
R E W O R K
C O N T E X T - S W I T C H I N G
= WA S T E .
![Page 41: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/41.jpg)
W H E N S H O U L D W E T E S T O U R C O D E ?
Write Test
Run Test
Code Run Test
Run Test
Run Test
![Page 42: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/42.jpg)
T E S T D R I V E N
1. Red - Write a failing test.
2. Green - Write code to make the test pass.
3. Refactor - Preserve the behavior. - Clean up the code.
![Page 43: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/43.jpg)
http://stackoverflow.com/questions/28372861/cucumber-js-for-bdd-unit-testing
![Page 44: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/44.jpg)
L E T S G E T T O W O R K !
https://github.com/dmorgan3405/ATDD-By-Example.git
git clone
![Page 45: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/45.jpg)
D E M O
• Open the browser
• Navigate to puppies.herokuapp.com
• Close the browser
Checkpoint: example_of_driving_a_browser
![Page 46: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/46.jpg)
PA R T D E U XA C C E P TA N C E T E S T D R I V E N D E V E L O P M E N T
![Page 47: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/47.jpg)
W O R K I N G A G R E E M E N T S ( R E M I N D E R )
• Help each other out. • You aren't done until the person next to you is done.
• Time boxed breaks. • Respect your peers; please don't be late.
• Ask questions. • Speak up if you don't understand something.
![Page 48: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/48.jpg)
T O O L B E LT
![Page 49: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/49.jpg)
C O M M O N LY U S E D R U B Y G E M S
• cucumber • watir-webdriver • page-object • rspec • nokogiri • active-record • factory_girl • savon • data_magic
![Page 50: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/50.jpg)
PA G E O B J E C T
“A simple gem that assists in creating flexible page objects for testing browser based applications. The goal is to facilitate creating abstraction layers in your tests to decouple the tests from the item they are testing and to provide a simple interface to the elements on a page. It works with both watir-webdriver and selenium-webdriver.”
* W W W. G I T H U B . C O M / C H E E Z Y / PA G E - O B J E C T / B L O B / M A S T E R / R E A D M E . M D
![Page 51: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/51.jpg)
P I C K A B R O W S E R
• Firefox • Nothing extra is needed.
• Chrome • Driver needed. (https://sites.google.com/a/chromium.org/chromedriver/downloads)
• Put in path.
• Internet Explorer • Driver needed. • Security Zones protection setting need to be the same. • Zoom set to 100%.
![Page 52: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/52.jpg)
PA G E O B J E C T A P I
Use the Quick reference guide inside of the repository!
![Page 53: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/53.jpg)
PA G E FA C T O R Y
To visit a page, then preform the action use
visit_page(HomePage).action_to_do
or
visit_page(HomePage) do |page| page.action_to_do end
![Page 54: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/54.jpg)
PA G E FA C T O R Y
To preform the action on the current page
on_page(HomePage).action_to_do
or
on_page(HomePage) do |page| page.action_to_do end
![Page 55: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/55.jpg)
L E T S A D O P T A P U P P Y !
![Page 56: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/56.jpg)
L E T S A D O P T A P U P P Y !
Feature: Adopting a puppy
As a puppy lover I want to adopt puppies So that ...
Background: Given I am on the puppy adoption site
Scenario: Adopting a puppy When I view the details of the first puppy And I choose to adopt the puppy And I enter my name "Your Name Here" And I enter my address "1151 N Marginal Rd" And I enter my email "[email protected]" And I choose to pay by "Credit card" And I choose to place my order Then I should see "Thank you for adopting a puppy!"
Checkpoint: start_adopting_a_puppy
![Page 57: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/57.jpg)
A D D I N G V E R I F I C AT I O N
How would you verify the thank you message is displayed?
Checkpoint: example_of_adding_verification
![Page 58: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/58.jpg)
W I T H C U C U M B E R TA B L E SH I G H E R L E V E L T E S T S
![Page 59: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/59.jpg)
Cucumber::MultilineArgument::DataTable
#hashes
Returns Array of Hashes
Checkpoint: start_using_cucumber_tables
![Page 60: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/60.jpg)
P O P U L AT E PA G E W I T H
This method will populate all matched page elements from the Hash passed as an argument.
• TextFields • TextAreas • SelectLists • FileFields • Checkboxes • Radio Buttons
The way it find an element is by matching the Hash key to the name you provided when declaring the element on your page.
![Page 61: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/61.jpg)
P O P U L AT E PA G E W I T H
class ExamplePage include PageObject
text_field(: name, :index => 0)
FORM_DATA = {:name => ‘Test User’}
def fill_form populate_page_with(FORM_DATA) end
end
Checkpoint: example_of_using_populate_page_with
![Page 62: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/62.jpg)
D ATA M A G I C
An easy to use gem that provides datasets that can be used by your application and tests. The data is stored in yaml files.
Checkpoint: example_of_data_magic
![Page 63: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/63.jpg)
N O W L E T S A D O P T T W O P U P P I E S !
Feature: Adopting multiple puppies
As a puppy lover I want to adopt multiple puppies So that ...
Background: Given I am on the puppy adoption site
Scenario: Adopting multiple puppies When I adopt puppy 1 And I choose to adopt another puppy And I adopt puppy 2 And I choose to complete the adoption And I checkout Then I should see "Thank you for adopting a puppy!"
Checkpoint: start_adopting_two_puppies
![Page 64: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/64.jpg)
S C E N A R I O O U T L I N E S
Checkpoint: start_using_scenario_outlines
Scenario Outline: Shopping cart offers common accessories When I adopt puppy 1 Then I should see "<accessory>" as an optional accessory Examples: | accessory | | Collar & Leash | | Chew Toy | | Travel Carrier | | First Vet Visit |
![Page 65: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/65.jpg)
TA B L E VA L I D AT I O N S
What should we tests?
![Page 66: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/66.jpg)
TA B L E VA L I D AT I O N S
• Verify one name, puppy price and cart total.
***Bonus***
• Verify two names, puppy prices, and cart total.
Checkpoint: start_validating_shopping_cart
![Page 67: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/67.jpg)
Q U E S T I O N S ?Q & A
![Page 68: ATDD BY Example With Cucumber](https://reader030.fdocuments.in/reader030/viewer/2022020203/58a5f7341a28aba5728b6ba5/html5/thumbnails/68.jpg)
T H A N K Y O U !
Jeff Morgan @chzy github.com/cheezy
Doug Morgan @dougmorgan_ github.com/dmorgan3405