Using Web-Based Automation Frameworks
When I first started programming, the mindset I had when learning new concepts were “What can I do with this library/language/framework”. Quite some time has passed, and with more tools under my belt, I more commonly find myself asking “What can my computer do for me?”.
Looking back, my short-term memory has always left something to be desired. This is why if you ever look at my phone or computer, you will see sticky notes of little tidbits that I wanted to remember, whether it be plans for the weekend, or a show on Netflix I was planning on starting. Sometimes things just slip my mind and fall between the cracks. I am notoriously terrible at remembering peoples birthdays, whether they be friends, relatives, pets. You name it. If only there was a solution to this problem that not only reminds me of birthdays and also solves the question “What to buy for a gift?”.
When I first learned about Capybara and what its purpose was, the lightbulb in my head lit up instantly. On wikipedia Capybara is listed as “a web-based automation software that simulates scenarios for user stories and automates web application testing for behavior-driven software development”. This sounds like a dream for any lazy programmer! Surely there are many complicated day-to-day things that could be automated, but I knew I had to start somewhere and I wanted to get my hands dirty with some Capybara scripts fast. I decided to use it to aid me in my problem of letting people down on their birthdays!
The goal of my first Capybara program is to have a script run everyday to check if it is someones birthday. If it is, I would like to navigate to a site to purchase a gift for them. I found the perfect gem to aid me in the “running everyday” problem ironically named “whenever”. The code below is set up so that it runs my spec Capybara file everyday at 9:00 am.
#The syntax for this part of my program looks like thisevery 1.day, at: => '9:00 am' do
command "../spec/order_flowers_spec.rb"
end
Next I would need specific data pertaining to the person whose birthday it was, which I decided to store in a User class. The helper methods I defined below are for filling out forms on the web and for running my test.
class Userattr_accessor :name, :loved_one_name, :loved_one_bday, :address, :zip, :credit_card, :cc_security_code, :email, :password, def initialize(args)
@name = args[:name]
@loved_one_name = args[:loved_one_name]
.
.
.
enddef bday_month
arr = loved_one_bday.split("-")
arr[1]
enddef bday_day
arr = loved_one_bday.split("-")
arr[0]
enddef is_loved_ones_birthday?
current_day = Date.today.day
current_month = Date.today.month
return current_day == bday_day && current_month == bday_month
endend
Now I needed to choose a gift to purchase the person whose birthday it was. This was quite challenging since usually repeat gifts are hardly every good ideas. However, things like flowers, chocolate, and teddy bears are always a good gift and there are same day delivery services for them. Because of those reasons I chose to purchase the gift from fromyouflowers.com.
Capybara also requires a web driver to function and I had the option of choosing from a couple, but the documentation and overall feedback of Selenium appeared superior so I went with the that. Upon further reading, a web driver is what Capybara interacts with via its DSL(domain specific language) which actually executes the actions seen on the webpage.
#set up capybara driver and homepage
Capybara.current_driver = :selenium
Capybara.app_host = 'http://www.fromyouflowers.com/'Next we need to set up a test that checks to see if flowers need to be ordered for someones birthday. Below is a snippet of the code which scrapes the site for urls and html tags to go through the process of ordering flowers.
#instantiate a user
args_hash = {name: "Luke Glayat" , loved_one_name: "name", loved_one_bday: '02-15-1970', address: "xxxxxx", zip: "xxxx", credit_card: "xxxxxx", cc_security_code: "xxxxx", email: "xxxxx", password: "xxxxxx"}
user = User.new(args_hash)# orders flowers if it is the morning of the loved ones birthday
describe "Birthday Checker" do
it 'checks users birthday and orders flowers' do if user.is_loved_ones_birthday? # navigate to login screen
visit "/"
find(:xpath, "//a[@href='url']").click # login
first("input[name='email']").set(user.email)
find("input[name='password']").set(user.password)
find("input[value='Log In »']").click # select bouquet to purchase and enter shipping info
visit "url"
visit 'url'
find("input[id='zip_code']").set(user.zip)
find("a", :text => /\AChoose a Delivery Date »\z/).click #proceed to checkout .
.
.end
Once I started actually coding with Capybara, I found it extremely easy to pick up due to readability of the syntax. The visit() method simply visits urls and the find() and first() methods take in HTML element parameters to find certain text fields to fill out and links to click. Ultimately I decided against filling out the form online with my credit card information and went with entering everything up until that point. From here, the user can fill in their secure information and complete their purchase.
All in all, watching my computer navigate the web and enter data into forms without touching anything looked like magic was oddly satisfying. In the future I would definitely aim to refactor some of this code to run every month and then order flowers accordingly if the event is occurring within the month.
