Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.
[~/srcPLgrado/mocha-chai-browser-demo(master)]$ mocha --help Usage: _mocha [debug] [options] [files] Commands: init <path> initialize a client-side mocha setup at <path> Options: -h, --help output usage information -V, --version output the version number -r, --require <name> require the given module -R, --reporter <name> specify the reporter to use -u, --ui <name> specify user-interface (bdd|tdd|exports) -g, --grep <pattern> only run tests matching <pattern> -i, --invert inverts --grep matches -t, --timeout <ms> set test-case timeout in milliseconds [2000] -s, --slow <ms> "slow" test threshold in milliseconds [75] -w, --watch watch files for changes -c, --colors force enabling of colors -C, --no-colors force disabling of colors -G, --growl enable growl notification support -d, --debug enable node's debugger, synonym for node --debug -b, --bail bail after first test failure -A, --async-only force all tests to take a callback (async) -S, --sort sort test files --recursive include sub directories --debug-brk enable node's debugger breaking on the first line --globals <names> allow the given comma-delimited global [names] --check-leaks check for global variable leaks --interfaces display available interfaces --reporters display available reporters --compilers <ext>:<module>,... use the given module(s) to compile files --inline-diffs display actual/expected differences inline within each string --no-exit require a clean shutdown of the event loop: mocha will not call process.exit
[~/srcPLgrado]$ mocha init chuchu [~/srcPLgrado]$ ls -ltr total 16 .... drwxr-xr-x 6 casiano staff 204 20 ene 11:16 chuchu [~/srcPLgrado]$ tree chuchu/ chuchu/ |-- index.html |-- mocha.css |-- mocha.js `-- tests.js
[~/srcPLgrado/mocha-tutorial]$ cat test/test.js var assert = require("assert") describe('Array', function(){ describe('#indexOf()', function(){ it('should return -1 when the value is not present', function(){ assert.equal(-1, [1,2,3].indexOf(5)); assert.equal(-1, [1,2,3].indexOf(0)); assert.equal( 0, [1,2,3].indexOf(99)); }) }) })
[~/srcPLgrado/mocha-tutorial]$ mocha . 0 passing (5ms) 1 failing 1) Array #indexOf() should return -1 when the value is not present: AssertionError: 0 == -1 at Context.<anonymous> (/Users/casiano/local/src/javascript/PLgrado/mocha-tutorial/test/test.js:7:14)
Mocha allows you to use any assertion library you want, if it throws an error, it will work! This means you can utilize libraries such as should.js, node's regular assert module, or others.
Mocha runs in the browser.
./mocha.js
and ./mocha.css
for use in the browser.
mocha.setup('bdd')
to use the BDD interface before loading the test
scripts, running them onload with mocha.run()
.
<html> <head> <meta charset="utf-8"> <title>Mocha Tests</title> <link rel="stylesheet" href="mocha.css" /> </head> <body> <div id="mocha"></div> <script src="jquery.js"></script> <script src="expect.js"></script> <script src="mocha.js"></script> <script>mocha.setup('bdd')</script> <script src="test.array.js"></script> <script src="test.object.js"></script> <script src="test.xhr.js"></script> <script> mocha.checkLeaks(); mocha.globals(['jQuery']); mocha.run(); </script> </body> </html>
mocha.globals([names ...])
A list of accepted global variable names. For example, suppose your app deliberately exposes a global named app and YUI
mocha.checkLeaks()
By default Mocha will not check for global variables leaked while running tests
The Mocha TDD interface provides suite()
, test()
, setup()
, and teardown()
.
suite('Array', function(){ setup(function(){ // ... }); suite('#indexOf()', function(){ test('should return -1 when not present', function(){ assert.equal(-1, [1,2,3].indexOf(4)); }); }); });
http://localhost:9876/
)
IFrame
40.1,
executes the tests and reports the results back to the server.
[~/srcPLgrado/mocha-chai-browser-demo(master)]$ karma --help Karma - Spectacular Test Runner for JavaScript. Usage: /usr/local/bin/karma <command> Commands: start [<configFile>] [<options>] Start the server / do single run. init [<configFile>] Initialize a config file. run [<options>] [ -- <clientArgs>] Trigger a test run. completion Shell completion for karma. Run --help with particular command to see its description and available options. Options: --help Print usage and options. --version Print current version.
In order to serve us well, Karma needs to know about our project in order to test it and this is done via a configuration file.
The configuration file can be generated using karma init
:
$ karma init my.conf.js Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > jasmine
Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no
Do you want to capture a browser automatically ? Press tab to list possible options. Enter empty string to move to the next question. > Chrome
What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. > Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes Config file generated at "/Users/casiano/local/src/javascript/PLgrado/mocha-tutorial/karma.conf.js".
The configuration file can be written in CoffeeScript as well. In fact,
if you execute karma init with a .coffee
filename extension, it will
generate a CoffeeScript file.
Of course, you can write the config file by hand or copy paste it from another project ;-)
[~/srcPLgrado/mocha-tutorial]$ cat karma.conf.js // Karma configuration // Generated on Mon Jan 20 2014 16:21:22 GMT+0000 (WET) module.exports = function(config) { config.set({ // base path, that will be used to resolve files and exclude basePath: '', // frameworks to use frameworks: ['jasmine'], // list of files / patterns to load in the browser files: [ ], // list of files to exclude exclude: [ ], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['progress'], // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes autoWatch: true, // Start these browsers, currently available: // - Chrome // - ChromeCanary // - Firefox // - Opera (has to be installed with `npm install karma-opera-launcher`) // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) // - PhantomJS // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) browsers: ['Chrome', 'Firefox'], // If browser does not capture in given timeout [ms], kill it captureTimeout: 60000, // Continuous Integration mode // if true, it capture browsers, run tests and exit singleRun: false }); };When starting Karma, the configuration file path can be passed in as the first argument. By default, Karma will look for
karma.conf.js
in the current directory.
# Start Karma using your configuration $ karma start my.conf.js
Some configurations, which are already present within the configuration file, can be overridden by specifying the configuration as a command line argument for when Karma is executed.
karma start karma-conf.js --command-one --command-two
[~/srcPLgrado/mocha-tutorial]$ karma start --help Karma - Spectacular Test Runner for JavaScript. START - Start the server / do a single run. Usage: /usr/local/bin/karma start [<configFile>] [<options>] Options: --port <integer> Port where the server is running. --auto-watch Auto watch source files and run on change. --no-auto-watch Do not watch source files. --log-level <disable | error | warn | info | debug> Level of logging. --colors Use colors when reporting and printing logs. --no-colors Do not use colors when reporting or printing logs. --reporters List of reporters (available: dots, progress, junit, growl, coverage). --browsers List of browsers to start (eg. --browsers Chrome,ChromeCanary,Firefox). --capture-timeout <integer> Kill browser if does not capture in given time [ms]. --single-run Run the test when browsers captured and exit. --no-single-run Disable single-run. --report-slower-than <integer> Report tests that are slower than given time [ms]. --help Print usage and options.
If we want to pass configuration options directly to mocha you can do this in the following way
// karma.conf.js module.exports = function(config) { config.set({ frameworks: ['mocha'], files: [ '*.js' ], client: { mocha: { ui: 'tdd' } } }); };(By default the
ui
is bdd
).
Here is an example (https://github.com/crguezl/nathanuniversityexercisesPL/blob/master/scheem8/karma.conf.js):
[~/srcPLgrado/nathansuniversity/exercises/scheem8(master)]$ cat karma.conf.js // Karma configuration // Generated on Tue Jan 21 2014 12:20:45 GMT+0000 (WET) module.exports = function(config) { config.set({ // base path, that will be used to resolve files and exclude basePath: '', // frameworks to use frameworks: ['mocha'], // list of files / patterns to load in the browser files: [ 'js/chai.js', 'js/jquery-1.10.2.js', 'js/mocha.js', 'js/scheem8.js', 'js/simpletest.js' ], // list of files to exclude exclude: [ ], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['progress'], // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes autoWatch: true, // Start these browsers, currently available: // - Chrome // - ChromeCanary // - Firefox // - Opera (has to be installed with `npm install karma-opera-launcher`) // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) // - PhantomJS // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) browsers: ['Chrome', 'Firefox'], // If browser does not capture in given timeout [ms], kill it captureTimeout: 60000, // Continuous Integration mode // if true, it capture browsers, run tests and exit singleRun: false, client: { mocha: { ui: 'tdd' } } }); };
If you have one html file:
[~/srcPLgrado/karma/html]$ cat template.html <div id="tpl">content of the template</div>which you want to load and then get all elements from that html page in your test script, you can use the
html2js
preprocessor, which basically converts
HTML files into JavaScript strings and include these files.
[~/srcPLgrado/karma/html]$ cat karma.conf.js module.exports = function(karma) { karma.configure({ basePath: '', frameworks: ['jasmine'], files: [ '*.js', '*.html' ], preprocessors: { '*.html': 'html2js' }, ....Then, you can access these strings in your test:
[~/srcPLgrado/karma/html]$ cat test.js describe('template', function() { it('should expose the templates to __html__', function() { document.body.innerHTML = __html__['template.html']; expect(document.getElementById('tpl')).toBeDefined(); }) })See
http://gruntjs.com/getting-started
npm install -g grunt-cli
A typical setup will involve adding two files to your project: package.json
and the
Gruntfile
.
package.json
: This file is used by npm
to store metadata for projects published as npm
modules.
You will list grunt and the Grunt plugins your project needs as devDependencies in this file.
Gruntfile
: This file is named Gruntfile.js
or Gruntfile.coffee
and is used to configure or define tasks and load Grunt plugins.
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.2", "grunt-contrib-jshint": "~0.6.3", "grunt-contrib-nodeunit": "~0.2.0", "grunt-contrib-uglify": "~0.2.2" } }
The Gruntfile.js or Gruntfile.coffee file is a valid JavaScript or CoffeeScript file that belongs in the root directory of your project, next to the package.json file, and should be committed with your project source.
A Gruntfile is comprised of the following parts:
In the following Gruntfile, project metadata is imported into the Grunt
config from the project's package.json
file and the
grunt-contrib-uglify
plugin's uglify task is configured to minify a source file and generate a banner comment dynamically using that metadata.
When grunt is run on the command line, the uglify task will be run by default.
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); };Now that you've seen the whole Gruntfile, let's look at its component parts.
Every Gruntfile (and gruntplugin) uses this basic format, and all of your Grunt code must be specified inside this function:
module.exports = function(grunt) { // Do grunt-related things in here };
Most Grunt tasks rely on configuration data defined in an object passed to the grunt.initConfig
method.
In this example,
grunt.file.readJSON('package.json')
imports the JSON metadata stored in
package.json
into the grunt config.
Because <% %>
template strings may reference any config properties, configuration data like filepaths and file lists may be specified this way to reduce repetition.
You may store any arbitrary data inside of the configuration object, and as long as it doesn't conflict with properties your tasks require, it will be otherwise ignored. Also, because this is JavaScript, you're not limited to JSON; you may use any valid JS here. You can even programmatically generate the configuration if necessary.
Like most tasks, the
grunt-contrib-uglify
plugin's uglify task expects its configuration
to be specified in a property of the same name.
Here, the banner
option is specified, along with a single uglify target
named build
that minifies a single source file to a single destination file.
// Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } });
https://github.com/UWMadisonUcomm/grunt-simple-example
[~/srcPLgrado/grunt-simple-example(master)]$ pwd /Users/casiano/srcPLgrado/grunt-simple-example [~/srcPLgrado/grunt-simple-example(master)]$ git remote -v origin git@github.com:UWMadisonUcomm/grunt-simple-example.git (fetch) origin git@github.com:UWMadisonUcomm/grunt-simple-example.git (push) [~/srcPLgrado/grunt-simple-example(master)]$ ls Gruntfile.js Readme.md assets index.html node_modules package.json src
[~/srcPLgrado/grunt-simple-example(master)]$ cat Gruntfile.js module.exports = function(grunt){ grunt.initConfig({ uglify: { main: { files: { 'assets/app.min.js': [ 'src/javascripts/jquery-1.10.2.min.js', 'src/javascripts/bootstrap.js', 'src/javascripts/application.js' ] } } }, less: { application: { options: { yuicompress: true }, files: { "assets/app.min.css": "src/stylesheets/application.less" } } }, watch: { javascripts: { files: ['src/javascripts/**/*'], tasks: ['uglify'] }, stylesheets: { files: ['src/stylesheets/**/*'], tasks: ['less'] } } }); // Load plugins grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); // Register tasks grunt.registerTask('default', ['uglify', 'less']); }
[~/srcPLgrado/grunt-simple-example(master)]$ cat package.json { "name": "grunt-simple-example", "version": "0.0.1", "main": "index.js", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-cssmin": "~0.6.2", "grunt-contrib-less": "~0.7.0", "grunt-contrib-uglify": "~0.2.4", "grunt-contrib-watch": "~0.5.3" }, "author": "Bryan Shelton", "license": "BSD-2-Clause" }
[~/srcPLgrado/grunt-simple-example(master)]$ npm install npm WARN package.json grunt-simple-example@0.0.1 No repository field. [~/srcPLgrado/grunt-simple-example(master)]$
[~/srcPLgrado/grunt-simple-example(master)]$ grunt watch Running "watch" task Waiting...OK >> File "src/javascripts/application.js" changed. Running "uglify:main" (uglify) task File "assets/app.min.js" created. Done, without errors. Completed in 3.897s at Mon Jan 20 2014 19:02:03 GMT+0000 (WET) - Waiting...
Project Pages are kept in the same repository as the project they are for.
These pages are similar to User and Org Pages, with a few slight differences:
gh-pages
branch is used to build and publish from.
username.github.io/projectnamePor ejemplo, mi usuario es
crguezl
. Si el proyecto se llama nathanuniversityexercisesPL
, la dirección será:
git clone https://github.com/user/repository.git # Clone our repository # Cloning into 'repository'... remote: Counting objects: 2791, done. remote: Compressing objects: 100% (1225/1225), done. remote: Total 2791 (delta 1722), reused 2513 (delta 1493) Receiving objects: 100% (2791/2791), 3.77 MiB | 969 KiB/s, done. Resolving deltas: 100% (1722/1722), done.
cd repository git checkout --orphan gh-pages # Creates our branch, without any parents (it's an orphan!) # Switched to a new branch 'gh-pages' git rm -rf . # Remove all files from the old working tree # rm '.gitignore'
echo "My GitHub Page" > index.html git add index.html git commit -a -m "First pages commit" git push origin gh-pages
Casiano Rodríguez León