Testing Meteor Apps
A bit about myself
- Meteor since June-14
- TDDer
- Early Velocity user
- "meteor-velocity" SO tag creator
Talk subjects
- Velocity
- Latte
- Debugging tests
- CI & CD
Velocity
What is Velocity?
"Ecosystem of testing tools"
Connects frameworks through a common API
Tests will run in the background while developing. You will get notified when something breaks.
Workflow Idea
Compatible testing frameworks
- mike:mocha
- sanjo:jasmine
- xolvio:cucumber
- html-reporter
- console-reporter
Common problems
- No tests => No CI
- Runs tests always
- Boots mirror processes
- Hard/Impossible to debug
- Different levels of maintenance
- Out of date documentation
Layered Early Stage of Development
Design flaws*: Mirrors
- Hard to debug tests
- Cumbersome to run both tests and app
- It uses a meteor **fork**
*in the eye of the beholder
Separate commands to run app and tests
Velocity: Coupled app and test runs
Latte: Coupled/independent blocking runs
What's great about mirros
Parallel non-blocking live testing
Idea behind Velocity
Unique out-of-the-box testing solution for Meteor
Latte
Simple, reliable testing
There should be no excuses not to tests
Running tests in the background can be misleading and a hassle. CI should prevent us from screwing it up.
Workflow Idea
-
Uses a separate DB
-
DB cleanup
-
Console report
-
Runs inside Meteor's env
Minimalistic approach towards Test Runner + Testing framework
Features
- Tested code
- Standard code style
- CI approach
- Simple to debug
- Runs on demand
- Lightweight
- Resembles mocha/rspec
Tested Code
Code coverage of... oh wait
Standard code style
feross/standard
CI Approach
- Run style checker
- Run tests
- Verify version bump on PRs
- Publish package on master builds
Simple: to debug
Debug your tests like you'd debug your app
Runs on demand
No hassle when starting your app
Lightweight
~250 lines of code
(Mocha/Rspec)-esque
Show me some code
global.Subjects = new Mongo.Collection('subjects')
describe('Subject seeding', function () {
context('there aren\'t any subjects in the DB', function () {
beforeEach(function () {
Seed.subjects()
})
it('should create new subjects', function () {
Subjects.find().count().should.be.gt(0)
})
})
context('there are already existing subjects in the DB', function () {
beforeEach(function () {
Subjects.insert({})
Seed.subjects()
})
it('should not create new subjects', function () {
Subjects.find().count().should.eq(1)
})
})
})
var Seed = {
subjects: function () {
if (!Subjects.find().count()) {
Subjects.insert({ name: 'name1'})
Subjects.insert({ name: 'name2'})
Subjects.insert({ name: 'name3'})
}
}
}
global.SampleCollection = new Mongo.Collection('sample_collections')
SampleCollection.remove({})
SampleCollection.insert({})
SampleCollection.find().count().should.eq(1)
describe('latte should use a separate DB from develop', function () {
it('should not see the entity created on develop\'s DB', function () {
SampleCollection.find().count().should.eq(0)
})
context('creating a new entity', function () {
beforeAll(function () {
SampleCollection.insert({ env: 'test' })
})
it('should see the entity created on test\'s DB', function () {
SampleCollection.find().count().should.eq(1)
})
})
})
var ddescribeCounter = 0
ddescribe('if there is a ddescribe block', function () {
it('should run assertions', function () {
ddescribeCounter++
})
describe('on nested blocks', function () {
it('should run assertions too', function () {
ddescribeCounter++
})
})
})
describe('unnested describe blocks in presence of a ddescribe block', function () {
it('should not run assertions', function () {
'a'.should.eq('b')
})
describe('on nested blocks', function () {
it('should not run assertions either', function () {
'a'.should.eq('b')
})
})
})
T.postRunCallbacks.push({
label: 'if there is a ddescribe block',
fn: function () {
if (ddescribeCounter !== 2) { throw new Error('ddescribe_spec: some assertion failed to exec. ddescribeCounter == ' + ddescribeCounter) }
}
})
Latte vs Velocity
Latte
- CI
- Lightweight
- Simple
- Package always up to date
- Standard code style
- Server side only by the moment
Velocity
- Team behind it
- Official testing framework
- Parallel testing
- HTML reporter
- Has been out for a while
- Variety of testing fws
Latte: Debugging
- Node Inspector - GUI
- Node Debugger - CLI
Node Inspector
Node Inspector
Node Inspector
Node CLI Debugger
CLI Reporter
- Lightweight
- First stop is your debugger line
- No need for UI/Chrome
- Debug without leaving TMUX
Inspector
- Call Stack travelling
- Chrome Dev Tools Goodness
Latte: CI & CD
sudo: required
language: node_js
branches:
only:
- master
before_install:
- curl https://install.meteor.com | /bin/sh
- npm install standard snazzy -g
script:
- snazzy
- sh run_tests.sh
- bash check_for_new_version_number.bash
- sh publish.sh
RUN_TESTS=1 LATTE_SUITES='["iit behaviour"]'meteor --once &&
RUN_TESTS=1 LATTE_SUITES='["if there is a ddescribe block"]' meteor --once ...
# Only on PR builds
if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then
diff <(git show master:packages/latte/package.js | grep -Po "version: \'.*?\',") <(git show HEAD:packages/latte/package.js | grep -Po "version: \'.*?\',")
version_changed=$?; if [ $version_changed != 0 ]; then
exit 0
else
echo 'Version needs to be bumped in order to merge PRs'
exit 1
fi
fi
# If not on a PR build => only on master
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]
then
echo 'Publishing package to Atmosphere'
printf $LI | meteor login &&
cd packages/latte && meteor publish
fi
Travis-CI
Testing Meteor Apps
By canotto90
Testing Meteor Apps
- 1,064