Session from GIDS 2014, showing how to do automated Web testing using a variety of JavaScript frameworks, including QUnit, Jasmine, Protractor, Selenium, and PhantomJS
The Python Cheat Sheet for the Busy MarketerHamlet Batista
What percentage of an Inbound marketer's day doesn't involve working with spreadsheets? How much of this work is time-consuming and repetitive? In this interactive session, you will learn how to manipulate Google Sheets to automate common data analysis workflows using Python, a very easy to use programming language.
Session from GIDS 2014, showing how to do automated Web testing using a variety of JavaScript frameworks, including QUnit, Jasmine, Protractor, Selenium, and PhantomJS
The Python Cheat Sheet for the Busy MarketerHamlet Batista
What percentage of an Inbound marketer's day doesn't involve working with spreadsheets? How much of this work is time-consuming and repetitive? In this interactive session, you will learn how to manipulate Google Sheets to automate common data analysis workflows using Python, a very easy to use programming language.
Creating and Deploying Static Sites with HugoBrian Hogan
Most web sites don’t have data that changes, so why power them with a database and take the performance hit? In this talk we’ll explore static site generation using Hugo, an open-source static site generator. You’ll learn how to make a master layout for all pages, and how to use Markdown to create your content pages quickly.
Then we’ll explore how to deploy the site we made to production. We’ll automate the entire process. When you’re done, you’ll be able to build and deploy static web sites quickly with minimal tooling.
Automating the Cloud with Terraform, and AnsibleBrian Hogan
Need a web server? So did I. But setting everything up by hand is tedious. In this talk, you'll see how to build a load-balanced web server using Ansible, Terraform, and DigitalOcean, a cloud provider aimed at developers. First, you'll see how to build out the servers and load balancer, and then you'll see how to use Ansible Playbooks to install and upload the web site. When we're done, you'll have scripts you can run to set up your own environment.
Create Development and Production Environments with VagrantBrian Hogan
Need a Linux box to test a Wordpress site or a Windows VM to test a web site on IE 10? Creating a virtual machine to test or deploy your software doesn’t have to be a manual process. Bring one up in seconds with Vagrant, software for creating and managing virtual machines. With Vagrant, you can bring up a new virtual machine with the software you need, share directories, copy files, and configure networking using a friendly DSL. You can even use shell scripts or more powerful provisioning tools to set up your software and install your apps. Whether you need a Windows machine for testing an app, or a full-blown production environment for your apps, Vagrant has you covered.
In this talk you’ll learn to script the creation of multiple local virtual machines. Then you’ll use the same strategy to provision production servers in the cloud.
I work with Vagrant, Terraform, Docker, and other provisioning systems daily and am excited to show others how to bring this into their own workflows.
Docker is an amazing tool, but unless you work with it every day, you're probably left with a ton of questions. What's a container? What's an image? What's the difference between Docker, Machine, Compose, and Swarm? Why the heck should I care? Well, Docker makes it easier than ever to deploy and scale your applications and services. In addition, it lets you simulate your production environment on your local machine without heavy virtual machines. In this talk, we'll explore the basics of Docker, create a custom image for a web application, create a group of containers, and look at how you can put your apps into production on various cloud providers. At the end of the talk, you'll have the knowledge you need to put this to use with your own applications.
Come explore Elm, a functional programming language for making web things. Elm aims to solve some of the same problems that Ember, React, and Angular 2 solve, but in a radically different way. Strong and static typing ensures that data you pass around in your apps really is what you think it is. A simple and tried-and-true architecture makes it easy to understand, and great tooling makes it fun to use.
If you've ever looked into how to create Gems, you've probably seen a bunch of ways to do that. Project generators like Hoe, Jeweler, and the like offer some nice ways to get started, but they may often be overkill for many projects. If you're just starting out, why not learn to do it from scratch?
In this talk, we'll create our own gem from scratch, using only things that are provided by Ruby, its standard library, and RubyGems to craft a simple gem.
You'll learn how to set up a project, how to write and run tests, how to use Rake to quickly build the gem, and even how to create a gem that installs an executable command-line program.
Intro talks never let you learn about the things that make a language truly cool. In this talk we'll discover how advanced features of Ruby help us write cleaner more modular code.
Web Development With Ruby - From Simple To ComplexBrian Hogan
Beyond the massive hype of Ruby on Rails, there's an amazing world of frameworks, DSLs, and libraries that make the Ruby language a compelling choice when working on the web. In this talk, you'll get a chance to see how to use Ruby to quickly build a static web site, create complex stylesheets with ease, build a simple web service, crete a simple Websocket server, and test your existing applications. Finally, you'll see a few of the ways Rails really can make developing complex applications easier, from advanced database querying to rendering views in multiple formats.
Stop Reinventing The Wheel - The Ruby Standard LibraryBrian Hogan
My talk from Ruby Hoedown MMX. We talked about the Ruby standard library and how sometimes we reinvent things when we have perfectly good tools waiting for us to use them.
Creating and Deploying Static Sites with HugoBrian Hogan
Most web sites don’t have data that changes, so why power them with a database and take the performance hit? In this talk we’ll explore static site generation using Hugo, an open-source static site generator. You’ll learn how to make a master layout for all pages, and how to use Markdown to create your content pages quickly.
Then we’ll explore how to deploy the site we made to production. We’ll automate the entire process. When you’re done, you’ll be able to build and deploy static web sites quickly with minimal tooling.
Automating the Cloud with Terraform, and AnsibleBrian Hogan
Need a web server? So did I. But setting everything up by hand is tedious. In this talk, you'll see how to build a load-balanced web server using Ansible, Terraform, and DigitalOcean, a cloud provider aimed at developers. First, you'll see how to build out the servers and load balancer, and then you'll see how to use Ansible Playbooks to install and upload the web site. When we're done, you'll have scripts you can run to set up your own environment.
Create Development and Production Environments with VagrantBrian Hogan
Need a Linux box to test a Wordpress site or a Windows VM to test a web site on IE 10? Creating a virtual machine to test or deploy your software doesn’t have to be a manual process. Bring one up in seconds with Vagrant, software for creating and managing virtual machines. With Vagrant, you can bring up a new virtual machine with the software you need, share directories, copy files, and configure networking using a friendly DSL. You can even use shell scripts or more powerful provisioning tools to set up your software and install your apps. Whether you need a Windows machine for testing an app, or a full-blown production environment for your apps, Vagrant has you covered.
In this talk you’ll learn to script the creation of multiple local virtual machines. Then you’ll use the same strategy to provision production servers in the cloud.
I work with Vagrant, Terraform, Docker, and other provisioning systems daily and am excited to show others how to bring this into their own workflows.
Docker is an amazing tool, but unless you work with it every day, you're probably left with a ton of questions. What's a container? What's an image? What's the difference between Docker, Machine, Compose, and Swarm? Why the heck should I care? Well, Docker makes it easier than ever to deploy and scale your applications and services. In addition, it lets you simulate your production environment on your local machine without heavy virtual machines. In this talk, we'll explore the basics of Docker, create a custom image for a web application, create a group of containers, and look at how you can put your apps into production on various cloud providers. At the end of the talk, you'll have the knowledge you need to put this to use with your own applications.
Come explore Elm, a functional programming language for making web things. Elm aims to solve some of the same problems that Ember, React, and Angular 2 solve, but in a radically different way. Strong and static typing ensures that data you pass around in your apps really is what you think it is. A simple and tried-and-true architecture makes it easy to understand, and great tooling makes it fun to use.
If you've ever looked into how to create Gems, you've probably seen a bunch of ways to do that. Project generators like Hoe, Jeweler, and the like offer some nice ways to get started, but they may often be overkill for many projects. If you're just starting out, why not learn to do it from scratch?
In this talk, we'll create our own gem from scratch, using only things that are provided by Ruby, its standard library, and RubyGems to craft a simple gem.
You'll learn how to set up a project, how to write and run tests, how to use Rake to quickly build the gem, and even how to create a gem that installs an executable command-line program.
Intro talks never let you learn about the things that make a language truly cool. In this talk we'll discover how advanced features of Ruby help us write cleaner more modular code.
Web Development With Ruby - From Simple To ComplexBrian Hogan
Beyond the massive hype of Ruby on Rails, there's an amazing world of frameworks, DSLs, and libraries that make the Ruby language a compelling choice when working on the web. In this talk, you'll get a chance to see how to use Ruby to quickly build a static web site, create complex stylesheets with ease, build a simple web service, crete a simple Websocket server, and test your existing applications. Finally, you'll see a few of the ways Rails really can make developing complex applications easier, from advanced database querying to rendering views in multiple formats.
Stop Reinventing The Wheel - The Ruby Standard LibraryBrian Hogan
My talk from Ruby Hoedown MMX. We talked about the Ruby standard library and how sometimes we reinvent things when we have perfectly good tools waiting for us to use them.
Testing Client-side Code with Jasmine and CoffeeScript
1. Testing Client-Side
Code
with CoffeeScript and Jasmine
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com Rate this talk at http://spkr8.com/t/8682
2. about me
I write books
I build things
I teach people
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
3. Why should we test
client-side code?
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
4. simple code is not
simple.
<img src="picture1.png" data-large-image="picture1-large.png">
<img src="picture2.png" data-large-image="picture2-large.png">
<img src="picture3.png" data-large-image="picture3-large.png">
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
5. simple code is not
simple.
$(function(){
if($(window).width() > 480){
var images = $("img");
images.each(function(index){
$(this).attr("src", $(this).attr("data-large-image"));
});
}
})
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
6. Lots of logic
Detecting the screen size
testing that each image got changed
checking that it only happens on
large screens
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
7. But client-side
testing can be hard!
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
8. Challenges
The DOM
Tightly-coupled code
Callbacks
We don’t know how to test
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
9. “Laws of Testing”
You may not write production code
until you have written a failing unit
test.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
10. “Laws of Testing”
You may not write more of a unit test
than is sufficient to fail, and not
compiling is failing
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
11. “Laws of Testing”
You may not write more production
code than is sufficient to pass the
currently failing test
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
12. But what if I don’t
know how to test the
feature?
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
14. You may not write production code
until you have written a failing unit
test.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
24. A Jasmine Test
describe("JavaScript's Math works!", function() {
it("adds numbers properly", function() {
var result = 5 + 5;
expect(result).toEqual(10);
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
25. Describe
describe("JavaScript's Math works!", function() {
it("adds numbers properly", function() {
var result = 5 + 5;
expect(result).toEqual(10);
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
26. it()
describe("JavaScript's Math works!", function() {
it("adds numbers properly", function() {
var result = 5 + 5;
expect(result).toEqual(10);
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
27. expect()
describe("JavaScript's Math works!", function() {
it("adds numbers properly", function() {
var result = 5 + 5;
expect(result).toEqual(10);
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
28. Jasmine Test
describe("The ImageReplacer object", function() {
it("replaces picture1 with picture1-large", function() {
ImageReplacer.replaceAll();
expect($("#picture1").attr("src")).toEqual("picture1-large.jpg");
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
29. Jasmine Test
describe("The ImageReplacer object", function() {
it("replaces picture1 with picture1-large", function() {
ImageReplacer.replaceAll();
expect($("#picture1").attr("src")).toEqual("picture1-large.jpg");
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
31. Jasmine Test
describe("The ImageReplacer object", function() {
it("replaces picture1 with picture1-large", function() {
ImageReplacer.replaceAll();
expect($("#picture1").attr("src")).toEqual("picture1-large.jpg");
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
32. Into this.
describe "JavaScript's Math works!", ->
it "adds numbers properly", ->
result = 5 + 5
expect(result).toEqual 10
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
33. CoffeeScript helps us
write better
JavaScript.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
34. CoffeeScript uses
significant whitespace
for scope.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
35. CoffeeScript borrows
from Python and Ruby
syntax.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
36. CoffeeScript compiles
to regular, plain old
JavaScript.
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
37. Declaring variables
and objects
var box, colors, firstName, lastName;
firstName = "Homer" firstName = "Homer";
lastName = "Simpson" lastName = "Simpson";
colors = ["Green", "Blue", "Red"] colors = ["Green", "Blue", "Red"];
box = box = {
height: 40 height: 40,
width: 60 width: 60,
color: red color: red
};
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
38. CoffeeScript uses function expressions.
hello (name) ->
alert "Hello #{name}"
var hello = function(name){
alert("Hello " + name + "!");
}
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
39. -> means
function(){}
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
40. Not bad...
describe("The ImageReplacer object", function() {
it("replaces picture1 with picture1-large", function() {
ImageReplacer.replaceAll();
expect($("#picture1").attr("src")).toEqual("picture1-large.jpg");
});
});
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
41. Much clearer.
describe "JavaScript's Math works!", ->
it "adds numbers properly", ->
result = 5 + 5
expect(result).toEqual 10
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
42. CoffeeScript wraps
everything in
(function(){ ... })()
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
43. CoffeeScript
Advantages
Everything wrapped in an anonymous
function
Less noise
Helps enforce good JS Style
Makes tests easier to read
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
44. cake
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
46. Project Structure
Project/
src/
ImageReplacer.coffee
spec/
ImageReplacer_spec.coffee
Cakefile
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
47. Jasmine-Standalone
https://github.com/pivotal/jasmine/
downloads
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
48. Demo
Write our ImageReplacer with
CoffeeScript, test-first.
Replace an image
Replace all images
Ensure mobile only
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
49. Requirements
Mobile sites (< 900 px wide) load
small images
Other sizes (> 900px wide) load
larger images
Only images with large images should
change
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
50. Demo
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
51. Async code?
Use spies!
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
53. describe "Searching Twitter", ->
it "creates an AJAX request to Twitter with the keyword 'JavaScript'", ->
expectedURL = "http://search.twitter.com/search.json?q=javascript"
twitter = new Twitter()
spy = spyOn($, "ajax")
twitter.search "javascript"
generatedURL = spy.mostRecentCall.args[0].url
expect(generatedURL).toEqual expectedURL
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
54. describe "Searching Twitter", ->
it "creates an AJAX request to Twitter with the keyword 'JavaScript'", ->
expectedURL = "http://search.twitter.com/search.json?q=javascript"
twitter = new Twitter()
spy = spyOn($, "ajax")
twitter.search "javascript"
generatedURL = spy.mostRecentCall.args[0].url
expect(generatedURL).toEqual expectedURL
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
55. describe "Searching Twitter", ->
it "creates an AJAX request to Twitter with the keyword 'JavaScript'", ->
expectedURL = "http://search.twitter.com/search.json?q=javascript"
twitter = new Twitter()
spy = spyOn($, "ajax")
twitter.search "javascript"
generatedURL = spy.mostRecentCall.args[0].url
expect(generatedURL).toEqual expectedURL
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
56. describe "Searching Twitter", ->
it "creates an AJAX request to Twitter with the keyword 'JavaScript'", ->
expectedURL = "http://search.twitter.com/search.json?q=javascript"
twitter = new Twitter()
spy = spyOn($, "ajax")
twitter.search "javascript"
generatedURL = spy.mostRecentCall.args[0].url
expect(generatedURL).toEqual expectedURL
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
57. What we learned
Putting things in objects makes them
more testable
CoffeeScript and Jasmine make tests
easier to read and write
Client-side code can be testable just
like server-side code
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
58. What next?
Explore Phantom.js for headless
testing
Integrate client-side testing into a
continuous integration server
Investigate other ways to create
objects
Brian P. Hogan http://spkr8.com/t/16851
twitter: @bphogan
www.bphogan.com
We have a web page that has images on the page. We want to think &#x201C;mobile first&#x201D; so we design for the small screen, using small images. We know we&#x2019;ll have large screens looking at our pages so we&#x2019;ll want to display large images too. So what we do is load the small images by default, and then load the large images using JavaScript. We place the sources to the large images in the custom data attributes of the images\n
Here&#x2019;s what the JavaScript for this might look like. We find all the image elements on the page with jQuery, then iterate over them and replace the attributes.\n
\n
\n
\n
\n
\n
\n
So that&#x2019;s all well and good for when you know what you&#x2019;re doing, but what do you do when you are doing something new that you&#x2019;ve never done before and don&#x2019;t know how to test?\n
You do a spike. You write some code and work out the details.\n
See, the first law of testing says you may not write PRODUCTION code. So you should do spikes. You should experiment and get to know your problem domain. Then you should throw it all away and rewrite it test-driven.\n
In order to write JavaScript code that&#x2019;s testable, we need to stop writing nasty messes of jQuery code thrown about all over our page. We need to start thinking about objects.\n
One of the keys to writing testable code is to start treating JavaScript as more than just a scripting language. It&#x2019;s an object-oriented language and it provides many of the capabilities that we would take advantage of in our other languages. The biggest of those is encapsulation.\n
There are lots of ways to define objects in JavaScript. There are some great books out there on the subject, but one of the most simple ways is to simply use an object literal. \n
Here&#x2019;s what the JavaScript for this might look like. We find all the image elements on the page with jQuery, then iterate over them and replace the attributes.\n
Remember this code? So this is just jQuery code without any encapsulation whatsoever. It would be much nicer if we could do something like this:\n
We can take all that messy code, put it in an object, and simply call that. Just by doing that alone, we&#x2019;ve now made it a lot easier to test. \n
But how do we actually do TDD in JavaScript? \n
\n
Jasmine is my testing framework of choice. It&#x2019;s simple, easy to read, has great support, lots of nice plugins, and can be set to run in the browser or in an automated fashion.\n
Jasmine tests are pretty simple.\n
Describe describes a behavior we&#x2019;re testing.\n
It() is an actual test declaration\n
Expect() runs some sort of check.\n
Using Jasmine, we simply write a test case using Jasmine&#x2019;s syntax that invokes our ImageReplacer object\n
then do an expects statement that checks to see if something worked. Of course it&#x2019;s a little more complicated than that.\n
One other thing I&#x2019;ve found incredibly useful for developing and testing this kind of code is CoffeeScript. \n
With CoffeeScript&#x2019;s syntax we can change this....\n
into this. \n
\n
\n
\n
\n
Variable declarations are all done by omitting the var keyword. CoffeeScript automatically adds this so we don&#x2019;t accidentally get a variable in the wrong scope.\n
\n
The skinny arrow in CoffeeScript basically means the function declaration in JavaScript. It&#x2019;s less typing and less parentheses and curly braces to match. \n
That matters a lot when doing things like this....\n
because we can make them look like this. It becomes much easier to read when doing nested functions.\n
When CoffeeScript is compiled to JavaScript, the JavaScript is all wrapped in an anonymous function which makes it much harder to accidentally pollute the global namespace.\n
\n
Cake is a build language that comes with CoffeeScript when you install it with Node.js&#x2019;s npm package manager. With cake we can set up a build system to automatically compile CoffeeScript files to JavaScript as we work.\n
With this simple Cakefile in our project, we can easily start working with CoffeeScript.\n
\n
We can download and unzip the Jasmine Standalone download. This gives us everything we need to start doing some BDD work.\n
\n
\n
\n
Heavy use of spies and mock objects can make your test suite run fast and keep it decoupled. For example:\n
The secret is to try to decouple things as much as possible.\n
I have a Twitter object\n
That Twitter object is going to do a jQuery AJAX call. I can spy on jQUery&#x2019;s ajax function.\n
When I call my Twitter object&#x2019;s search method, it won&#x2019;t actually call out to Twitter. But I can pretend it did and I can then check to ensure the URL my object constructed was correctly built from the search term. \n
See? Here&#x2019;s the assertion. When I created the spy I could have actually fed it a response that I could then parse out. So I can write these tests without ever hitting the server.\n