Sunday, June 3, 2012

Setting up Selenium with Ruby, RSpec and MySQL

This took me about a day of working to get figured out some of the details, so I figured I'd share. I'm running a LAMP server on a virtual machine, so I configured everything for remote access.

Download Selenium Server locally - set up a script or alias for it, to make things easier, as you'll need to run it whenever you run tests.
On your server, install rvm. Use it to install the most recent version of ruby, which will come with rubygems.
Install gems:
gem install selenium-webdriver
gem install rspec
gem install mysql
Now, add some lines to your test file (along with gem requires). Bold text should be filled in with your details.
driver = Selenium::WebDriver.for :remote, :url => "http://localhost:port/wd/hub", :desired_capabilities => :chrome
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
dbh = Mysql.real_connect(address, user, password, database)
You can use "wait" later to wait for particular events (like "wait.until { driver.find_element(:class => something) }"). The timeout is how long it'll wait in seconds.
The "dbh" variable you set to your mysql connection can be used for running sql queries, though it'll return a query object which you'll need to parse to make meaningful.

You'll need to download ChromeDriver and extract it into where the Selenium Server is located, if you want to test using Chrome (pro-tip: set up a config file and have configs for every major browser, if you're serious about testing).

If everything's working properly, you should be able to automate browser functions (by running rspec tests in your virtual machine using a remote shell), which will allow you to automate server SQL querying to validate changes to the database. The tests should just be rspec assertions based on SQL query results. Even nicer, you should be able to set up Growl locally if you're running OSX (might try this next - I've used it for Ruby on Rails rspec tests and it's pretty cool).

Wednesday, May 2, 2012

Interview Questions

I was interviewing at a startup yesterday and had a moment when I realized that they were one of the most legit places I'd visited since moving here. They gave me a FizzBuzz-like problem that I solved without effort. "You know, you can give me an algorithm question if you want." I'd spent the night before reviewing data structures and algorithms questions, as I was becoming accustomed to being peppered with them. "Why would we ask you to reimplement a linked list when that's not representative of what you'd do here?"

Wow. All of the questions they asked me that day were practical ones - they were interested in my experiences, my beliefs, and my thought processes. How I would implement a feature, what would I want to test, and why did I choose x language for y project?

I had an awful phone interview two weeks earlier where I was asked minor details about C++ STL data structures. I stumbled a bit and was told that I "wasn't the right fit". Having an experience like yesterday's was tremendously refreshing and made me respect the company and its engineers that much more.

edit: They made an offer the next day. I accepted :)

Thursday, April 5, 2012

Quicksort

I wrote three different Quicksort algorithms for coursera's algorithms course, using different pivot points and calculating the relative amounts of work done. For those familiar with the algorithm, each level of recursion should divide the current subproblem in a 25-75 split or better (closer to 50-50 is better). This is necessary to maintain $O(nlogn)$ complexity - at its worst, Quicksort can be $O(n^2)$ if poorly implemented in a worst case.

Anyways, I was copying my array before running a quicksort function on it for each of the three implementations - I remember thinking "Gee, this would suck if Ruby does shallow copies of arrays". A bit of debugging later, and I realized that this is exactly what Ruby does - instead of copying an array, you now have multiple pointers to the same array, in order to prevent large wastes of space. The solution is to call .dup on the array when making a copy, but I found an interesting point by the co-author of Ruby Best Practices. They pointed out that, in most cases, needing to duplicate your array is a sign of a bad programming solution. If you've planned out your code well enough, it shouldn't be necessary. Now, in this case, I'm required to do unnecessary work just in order to test effective Quicksort pivoting and don't feel too badly about this. In the future, I think I'll keep this in mind.

Friday, March 30, 2012

Eurekamap

Eurekamap is live now, and scraping data hourly. It took a few days of work, and my friend has been amazing in showing me the ropes to some of the more complex aspects of javascript (as well as css tips and a hundred other things). So, what did we learn from this experience?

Twitter Bootstrap is a Pain

The framework is great for some things - scalability, elegant jquery plugins, and nice fractional page segmentation. My biggest frustration was just in feeling like I needed to fight against bootstrap every time I wanted to do something that wasn't a supported feature. It was a cool experience trying it, and I might use it again for smaller or particular projects, but I think I'll forgo it the next time I build a Rails app.

Saturday, March 24, 2012

Changes

Three weeks ago I came to San Francisco to spend time with a friend before my PhD interview at Irvine. I made a Big Scary Decision™ to cancel my grad school interviews and pursue a job at a startup here. The girl I'm staying with is one of the most inspiring people I've ever met, and this has been an exciting period of personal growth thus far. I feel like I have a real opportunity right now, and I'm young enough that I can chase after my dream of creating something amazing.


So, I'm focusing heavily on front-end work at the moment. Rails is pretty excellent and I learned how to automate rake tasks for fun Nokogiri magic. My next site will be live once I push it to heroku and clean up some CSS.


What I figured I'd ramble about is closures in javascript. I was having trouble with a function I'd created in a loop - it was supposed to be setting google map API markers and giving them info windows and associated listeners. Because of the way that javascript scoping works, it iterates through the loop and each marker was given the same information for info windows. By using closures, you can effectively create separate scopes (javascript scopes are function-level), preventing this from happening.

Thursday, February 16, 2012

Piled high and Deeper

I have a few interviews for PhD programs starting next week. I had an excel file that I'd worked on for a year of programs I was going to apply to - in the end, I only applied to half, realizing that my safety schools didn't really excite me enough to warrant interest in them1. I've been fortunate enough to draw interest from some programs that interest me.

It's a little scary that, in 6-8 weeks, I'll be making a major decision that could affect the next few years of my life (and, ultimately, the rest of my life). Not only do I have to decide on a program, but I have to decide whether I can be happy obsessively delving into one small region of a field for the next 5-6 years. With the right program and the right advisor, this seems doable. Regardless, it isn't something I'll jump into unless I feel completely comfortable doing so after visiting universities. There's such a huge opportunity cost, especially given my interest in tech start-ups.

~

1Most people advise applying to 8-10 PhD programs, with a mix of schools that you're likely to gain acceptance at and schools that you are less likely to gain acceptance at.

Sunday, January 22, 2012

PyChallenge (3/20) - Primality Testing

It seems that, once again, best intentions have been impeded by mandatory coursework. I have a few hundred pages to read this weekend and an essay to write. I still intend to continue this blog series, even if I can't adhere to a strict timeline. Some of the more complex algorithms I've been reading about are a bit time-consuming to wrap my head around. My data structures coursework required implementation of some optimal path algorithms, and I've found since then that the best way to understand and permanently assimilate something is to implement it myself. So, back to the code!

I was first exposed to primality testing when learning about Fermat's Little Theorem in discrete math, which states that given some prime $p$ and some integer $a$ such that $1 \le a < p$:

$a^{p-1} \equiv 1 (mod  p)$

This can be used to estimate primality, and is used as such for PGP key generation. However, a small fraction of numbers that will appear prime to FLT are actually composite, known as Carmichael Numbers. It's been proven that these are infinite in number.

A decade ago, a team of researchers developed the AKS Primality Test, which showed that primality testing is a member of P since it can be completed deterministically. This is interesting from a theoretical perspective, but still slower than some probabilistic methods.

So, on to something more practical: the Miller-Rabin Primality Test. This is another probabilistic test - I've been told that its error rate is $(\frac{1}{4})^n$ where $n$ is the number of iterations, though I need to hunt down a better source for this. It's derived from similar logic as the FLT test, but without its flaws.

Edit: This Cornell handout is much more thorough on the issue.