updates, time to do this
This commit is contained in:
parent
c631bb6279
commit
c654a753c5
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.DS_Store
|
||||
.sass-cache/
|
||||
|
||||
_export/
|
||||
_site/
|
||||
|
@ -11,6 +11,7 @@ PATH
|
||||
pygments.rb
|
||||
rack (~> 1.4.0)
|
||||
rdiscount
|
||||
selenium-webdriver
|
||||
sinatra
|
||||
sprockets
|
||||
sprockets-sass
|
||||
@ -53,6 +54,8 @@ GEM
|
||||
rails (>= 3.0.0)
|
||||
blankslate (2.1.2.4)
|
||||
builder (3.0.0)
|
||||
childprocess (0.3.1)
|
||||
ffi (~> 1.0.6)
|
||||
chunky_png (1.2.5)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
@ -128,7 +131,13 @@ GEM
|
||||
rubypython (0.5.3)
|
||||
blankslate (>= 2.1.2.3)
|
||||
ffi (~> 1.0.7)
|
||||
rubyzip (0.9.6.1)
|
||||
sass (3.1.15)
|
||||
selenium-webdriver (2.20.0)
|
||||
childprocess (>= 0.2.5)
|
||||
ffi (~> 1.0)
|
||||
multi_json (~> 1.0)
|
||||
rubyzip
|
||||
sinatra (1.3.2)
|
||||
rack (~> 1.3, >= 1.3.6)
|
||||
rack-protection (~> 1.2)
|
||||
|
1453
_site/index.html
1453
_site/index.html
File diff suppressed because it is too large
Load Diff
@ -3,5 +3,7 @@ require 'rack-livereload'
|
||||
Attentive.configure do |c|
|
||||
c.title = "Tea Time: A Beginner's Guide to Jasmine"
|
||||
c.middleware << Rack::LiveReload
|
||||
|
||||
#c.export_size = '1280x1024'
|
||||
end
|
||||
|
||||
|
@ -20,10 +20,8 @@
|
||||
!SLIDE
|
||||
# Fortunately, we're beyond that nowadays
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` ruby
|
||||
require 'spec_helper'
|
||||
|
||||
describe MyCoolWebsite do
|
||||
let(:website) { described_class.new }
|
||||
|
||||
@ -34,7 +32,8 @@ describe MyCoolWebsite do
|
||||
let(:double_cool) { 'double cool' }
|
||||
|
||||
before do
|
||||
website.stubs(:whoa_cool).returns(oh_yeah)
|
||||
website.stubs(:whoa_cool).
|
||||
returns(oh_yeah)
|
||||
end
|
||||
|
||||
it { should == double_cool }
|
||||
@ -52,31 +51,38 @@ end
|
||||
onmouseout="this.src='normal.gif'" />
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
``` html
|
||||
<script type="text/javascript">
|
||||
!SLIDE even-larger
|
||||
``` javascript
|
||||
function showMyCoolTitle(title, length) {
|
||||
if (length == null) { length = 0; }
|
||||
|
||||
if (length <= title.length) {
|
||||
document.title = title.substr(0, length);
|
||||
document.title =
|
||||
title.substr(0, length);
|
||||
|
||||
length++;
|
||||
|
||||
setTimeout(function() { showMyCoolTitle(title, length); }, 75);
|
||||
setTimeout(function() {
|
||||
showMyCoolTitle(title, length);
|
||||
}, 75);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
!SLIDE even-larger
|
||||
``` javascript
|
||||
window.onload = function() {
|
||||
showMyCoolTitle("My cool website! Whoaaaaa!");
|
||||
showMyCoolTitle(
|
||||
"My cool website! Whoaaaaa!"
|
||||
);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
# jQuery
|
||||
|
||||
!SLIDE
|
||||
# Backbone
|
||||
# Backbone.js
|
||||
|
||||
!SLIDE
|
||||
# Sprockets and RequireJS
|
||||
@ -84,10 +90,8 @@ window.onload = function() {
|
||||
!SLIDE
|
||||
# Automated testing is important
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` ruby
|
||||
require 'spec_helper'
|
||||
|
||||
describe MyCoolWebsite do
|
||||
let(:website) { described_class.new }
|
||||
|
||||
@ -98,7 +102,8 @@ describe MyCoolWebsite do
|
||||
let(:double_cool) { 'double cool' }
|
||||
|
||||
before do
|
||||
website.stubs(:whoa_cool).returns(oh_yeah)
|
||||
website.stubs(:whoa_cool).
|
||||
returns(oh_yeah)
|
||||
end
|
||||
|
||||
it { should == double_cool }
|
||||
@ -106,23 +111,22 @@ describe MyCoolWebsite do
|
||||
end
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'MyCoolWebsiteView', ->
|
||||
website = null
|
||||
|
||||
beforeEach ->
|
||||
website = new MyCoolWebsiteView()
|
||||
@website = new MyCoolWebsiteView()
|
||||
|
||||
describe '#coolMethod', ->
|
||||
doubleCool = 'double cool'
|
||||
ohYeah = [ doubleCool ]
|
||||
|
||||
beforeEach ->
|
||||
website.whoaCool = -> ohYeah
|
||||
@website.whoaCool = -> ohYeah
|
||||
|
||||
it 'should be double cool', ->
|
||||
expect(website.coolMethod()).toEqual(doubleCool)
|
||||
expect(@website.coolMethod()).
|
||||
toEqual(doubleCool)
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
|
@ -22,16 +22,17 @@ describe 'Cat', ->
|
||||
!SLIDE image-80-percent
|
||||
<img src="assets/cat-meow.jpg" />
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
# description of the meow behavior goes here
|
||||
# description of the
|
||||
# meow behavior goes here
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
!SLIDE larger
|
||||
# John behavior #1
|
||||
## Use Ruby-style indicators for instance- and class-level methods, even in Jasmine
|
||||
## Use Ruby-style indicators for instance- and class-level methods
|
||||
|
||||
``` coffeescript
|
||||
describe 'John', ->
|
||||
|
@ -29,7 +29,7 @@ describe 'Cat', ->
|
||||
``` coffeescript
|
||||
# code-under-test
|
||||
|
||||
class this.Cat
|
||||
class @Cat
|
||||
meow: ->
|
||||
```
|
||||
|
||||
@ -37,7 +37,6 @@ class this.Cat
|
||||
``` javascript
|
||||
// safety wrapper to prevent global pollution
|
||||
(function() {
|
||||
// ...but we want to pollute the Cat class
|
||||
this.Cat = (function() {
|
||||
function Cat() {}
|
||||
Cat.prototype.meow = function() {};
|
||||
@ -61,7 +60,7 @@ Expected undefined to equal 'meow'.
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
meow: -> "meow"
|
||||
```
|
||||
|
||||
@ -87,6 +86,6 @@ describe 'Cat', ->
|
||||
``` coffeescript
|
||||
# code-under-test
|
||||
|
||||
class this.Cat
|
||||
class @Cat
|
||||
meow: -> "meow"
|
||||
```
|
||||
|
@ -10,7 +10,7 @@
|
||||
!SLIDE
|
||||
# Nested `describe`
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
@ -23,19 +23,20 @@ describe 'Cat', ->
|
||||
# the cat knows it's vet time
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
describe 'hungry', ->
|
||||
describe 'hungry', ->
|
||||
it 'should be a mournful meow', ->
|
||||
cat = new Cat()
|
||||
cat.state = -> Cat.HUNGRY
|
||||
# ...just like cat.stubs(:state)
|
||||
|
||||
expect(cat.meow()).toEqual("meeeyaow")
|
||||
```
|
||||
|
||||
describe 'going to the vet', ->
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'going to the vet', ->
|
||||
it 'should be an evil meow', ->
|
||||
cat = new Cat()
|
||||
cat.state = -> Cat.VET_PSYCHIC
|
||||
@ -95,20 +96,26 @@ it "should be in the same context", ->
|
||||
expect(@instanceVariable).toEqual("yes")
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
beforeEach ->
|
||||
@cat = new Cat()
|
||||
```
|
||||
|
||||
describe 'hungry', ->
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'hungry', ->
|
||||
it 'should be a mournful meow', ->
|
||||
@cat.state = -> Cat.HUNGRY
|
||||
|
||||
expect(@cat.meow()).toEqual("meeeyaow")
|
||||
```
|
||||
|
||||
describe 'going to the vet', ->
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'going to the vet', ->
|
||||
it 'should be an evil meow', ->
|
||||
@cat.state = -> Cat.VET_PSYCHIC
|
||||
|
||||
|
@ -15,7 +15,7 @@ describe 'Cat', ->
|
||||
!SLIDE
|
||||
# This works, but it can be clearer
|
||||
|
||||
!SLIDE
|
||||
!SLIDE even-larger
|
||||
``` ruby
|
||||
describe Cat do
|
||||
describe '#meow' do
|
||||
@ -41,12 +41,13 @@ end
|
||||
alias :context :describe
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` ruby
|
||||
describe Cat do
|
||||
let(:cat) { described_class.new }
|
||||
|
||||
# save describe for things or behaviors...
|
||||
# save describe for
|
||||
# things or behaviors...
|
||||
describe '#meow' do
|
||||
subject { cat.meow }
|
||||
|
||||
@ -110,7 +111,7 @@ describe 'Cat', ->
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
@HUNGRY = 'hungry'
|
||||
@VET_PSYCHIC = 'vet psychic'
|
||||
|
||||
|
@ -12,7 +12,7 @@ cat.should_not be_hungry
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
expect(cat.meow()).toEqual("meow")
|
||||
expect(cat.prototype).toEqual(Cat.prototype)
|
||||
expect(cat.constructor).toEqual(Cat)
|
||||
expect(cat.isHungry()).not.toBeTruthy()
|
||||
```
|
||||
|
||||
@ -46,7 +46,10 @@ MyMatchers =
|
||||
|
||||
beforeEach ->
|
||||
this.addMatchers(MyMatchers)
|
||||
```
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
beforeEach ->
|
||||
@cat = new Cat()
|
||||
|
@ -36,19 +36,19 @@ describe 'John', ->
|
||||
!SLIDE image-80-percent
|
||||
<img src="assets/beer-cat.jpg" />
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` gherkin
|
||||
Feature: Cat Behaviors
|
||||
Scenario: Hungry cats meow a particular way
|
||||
Scenario: Hungry cats meow a certain way
|
||||
Given I have a cat
|
||||
And the cat is hungry
|
||||
When the cat meows
|
||||
Then the meow should sound like "meeyaow"
|
||||
Then the meow should be a "meeyaow"
|
||||
```
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
@FOOD_THRESHOLD = 20
|
||||
@HUNGRY = 'hungry'
|
||||
|
||||
@ -64,7 +64,7 @@ class this.Cat
|
||||
Cat.HUNGRY
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
@ -73,17 +73,19 @@ describe 'Cat', ->
|
||||
cat = new Cat()
|
||||
cat.foodLevel = 15
|
||||
|
||||
expect(cat.meow()).toEqual("meeeyaow")
|
||||
expect(cat.meow()).
|
||||
toEqual("meeeyaow")
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
# A perfectly cromulent test
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
meow: ->
|
||||
switch this.state() # <= dependent code executed
|
||||
switch this.state()
|
||||
# ^^^ dependent code executed
|
||||
when Cat.HUNGRY
|
||||
"meeyaow"
|
||||
```
|
||||
@ -91,25 +93,24 @@ class this.Cat
|
||||
!SLIDE
|
||||
# Why make your unit tests fragile?
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
cat.foodLevel = 15
|
||||
# do we care about food level in this test?
|
||||
# all we care about is that the cat is hungry
|
||||
# do we care about food level?
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'Cat', ->
|
||||
describe '#meow', ->
|
||||
describe 'hungry', ->
|
||||
context 'hungry', ->
|
||||
it 'should be a mournful meow', ->
|
||||
cat = new Cat()
|
||||
cat.state = -> Cat.HUNGRY
|
||||
# ^^^ we don't care how state works,
|
||||
# we just want a hungry cat
|
||||
# ^^^ we just want a hungry cat
|
||||
|
||||
expect(cat.meow()).toEqual("meeeyaow")
|
||||
expect(cat.meow()).
|
||||
toEqual("meeeyaow")
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
@ -117,7 +118,7 @@ describe 'Cat', ->
|
||||
## Just replace the method on the instance
|
||||
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
state: ->
|
||||
# cat codes
|
||||
|
||||
@ -148,7 +149,7 @@ cat.state = -> "whatever"
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
vocalProcessor: (speech) =>
|
||||
if this.isAirborne()
|
||||
this.modifyForAirborne(speech)
|
||||
@ -156,7 +157,7 @@ class this.Cat
|
||||
this.modifyForGround(speech)
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
!SLIDE larger
|
||||
``` coffeescript
|
||||
describe 'Cat#vocalProcessor', ->
|
||||
speech = "speech"
|
||||
@ -171,7 +172,8 @@ describe 'Cat#vocalProcessor', ->
|
||||
|
||||
it 'should be modified for flight', ->
|
||||
@cat.vocalProcessor(speech)
|
||||
expect(@cat.modifyForAirborne).toHaveBeenCalledWith(speech)
|
||||
expect(@cat.modifyForAirborne).
|
||||
toHaveBeenCalledWith(speech)
|
||||
```
|
||||
|
||||
!SLIDE even-larger
|
||||
@ -187,48 +189,53 @@ spyOn(@cat, 'modifyForAirborne')
|
||||
!SLIDE
|
||||
# Two basic ways to make sure a spy is called
|
||||
|
||||
!SLIDE
|
||||
!SLIDE even-larger
|
||||
## `toHaveBeenCalledWith(args...)`
|
||||
### Called least once with the given parameters
|
||||
|
||||
``` coffeescript
|
||||
expect(@cat.modifyForAirborne).toHaveBeenCalledWith(speech)
|
||||
expect(@cat.modifyForAirborne).
|
||||
toHaveBeenCalledWith(speech)
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
!SLIDE even-larger
|
||||
## `toHaveBeenCalled()`
|
||||
### Just called, no parameter check
|
||||
|
||||
``` coffeescript
|
||||
expect(@cat.modifyForAirborne).toHaveBeenCalled()
|
||||
expect(@cat.modifyForAirborne).
|
||||
toHaveBeenCalled()
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
# Instance Mocks/Spies in JavaScript
|
||||
## Use `spyOn`/`toHaveBeenCalled` matchers
|
||||
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
state: ->
|
||||
# cat codes
|
||||
|
||||
cat = new Cat()
|
||||
spyOn(cat, 'state')
|
||||
expect(cat.state).toHaveBeenCalled()
|
||||
expect(cat.state).
|
||||
toHaveBeenCalled()
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
# `spyOn` works great with class-level stubs and mocks, too
|
||||
|
||||
!SLIDE
|
||||
!SLIDE larger
|
||||
``` coffeescript
|
||||
class this.Cat
|
||||
class @Cat
|
||||
@generateFurColor: (base) ->
|
||||
# magicks to make a fur color given a base
|
||||
|
||||
regrowFur: (damagedHairs) ->
|
||||
for follicle in damagedHairs
|
||||
follicle.regrow(Cat.generateFurColor(this.baseColor))
|
||||
follicle.regrow(
|
||||
Cat.generateFurColor(this.baseColor)
|
||||
)
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
@ -237,26 +244,26 @@ Cat.generateFurColor = ->
|
||||
"whoops i nuked this method for every other test"
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
!SLIDE larger
|
||||
``` coffeescript
|
||||
describe 'Cat#regrowFur', ->
|
||||
color = 'color'
|
||||
|
||||
beforeEach ->
|
||||
@cat = new Cat()
|
||||
@follicle =
|
||||
regrow: ->
|
||||
|
||||
@follicle = { regrow: -> null }
|
||||
@follicles = [ follicle ]
|
||||
|
||||
spyOn(Cat, 'generateFurColor').andReturn(color)
|
||||
# ^^^ original is replaced when done
|
||||
spyOn(Cat, 'generateFurColor').
|
||||
# ^^^ original replaced when done
|
||||
andReturn(color)
|
||||
spyOn(@follicle, 'regrow')
|
||||
|
||||
it 'should regrow', ->
|
||||
@cat.regrowFur(@follicles)
|
||||
|
||||
expect(@follicle.regrow).toHaveBeenCalledWith(color)
|
||||
expect(@follicle.regrow).
|
||||
toHaveBeenCalledWith(color)
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
@ -329,7 +336,7 @@ describe 'Cat#fetch', ->
|
||||
!SLIDE
|
||||
# Sometimes you just need a big blob of unit tests
|
||||
|
||||
!SLIDE
|
||||
!SLIDE larger
|
||||
``` coffeescript
|
||||
# fast and focused!
|
||||
|
||||
@ -339,8 +346,11 @@ describe 'Cat#respondsTo', ->
|
||||
|
||||
context 'successes', ->
|
||||
it 'should respond', ->
|
||||
for request in [ 'kitty kitty', 'pookums', 'hisshead' ]
|
||||
expect(@cat.respondsTo(request)).toBeTruthy()
|
||||
for request in [ 'kitty kitty',
|
||||
'pookums',
|
||||
'hisshead' ]
|
||||
expect(@cat.respondsTo(request)).
|
||||
toBeTruthy()
|
||||
```
|
||||
|
||||
!SLIDE larger
|
||||
|
@ -7,16 +7,20 @@
|
||||
!SLIDE
|
||||
# Mocking and stubbing `$.fn` calls
|
||||
|
||||
!SLIDE
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
this.containerWaiter = ->
|
||||
$('#container').addClass('wait').append('<div class="waiting" />')
|
||||
$('#container').
|
||||
addClass('wait').
|
||||
append('<div class="waiting" />')
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
$.fn.makeWait = ->
|
||||
$(this).addClass('wait').append('<div class="waiting" />')
|
||||
$(this).
|
||||
addClass('wait').
|
||||
append('<div class="waiting" />')
|
||||
this
|
||||
```
|
||||
|
||||
@ -29,7 +33,7 @@ this.containerWaiter = ->
|
||||
!SLIDE
|
||||
# `jquery-jasmine`
|
||||
|
||||
!SLIDE larger
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
describe 'container', ->
|
||||
beforeEach ->
|
||||
@ -37,8 +41,11 @@ describe 'container', ->
|
||||
|
||||
it 'should make it wait', ->
|
||||
containerWaiter()
|
||||
expect($('#container')).toHaveClass('wait')
|
||||
expect($('#container')).toContain('div.waiting')
|
||||
|
||||
expect($('#container')).
|
||||
toHaveClass('wait')
|
||||
expect($('#container')).
|
||||
toContain('div.waiting')
|
||||
```
|
||||
|
||||
!SLIDE image-80-percent
|
||||
@ -67,7 +74,8 @@ describe 'container', ->
|
||||
|
||||
it 'should make it wait', ->
|
||||
containerWaiter()
|
||||
expect($.fn.makeWait).toHaveBeenCalled()
|
||||
expect($.fn.makeWait).
|
||||
toHaveBeenCalled()
|
||||
```
|
||||
|
||||
!SLIDE
|
||||
@ -78,7 +86,7 @@ describe 'container', ->
|
||||
|
||||
!SLIDE even-larger
|
||||
``` coffeescript
|
||||
class Cat
|
||||
class @Cat
|
||||
constructor: ->
|
||||
@mood = "happy"
|
||||
|
||||
|
@ -45,6 +45,4 @@ runs()
|
||||
|
||||
!SLIDE
|
||||
# Thank you!
|
||||
## [@johnbintz](http://twitter.com/johnbintz/)
|
||||
## [GitHub](http://github.com/johnbintz/)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user