mhevery / jasmine-node

Integration of Jasmine Spec framework with Node.js
MIT License
1.52k stars 292 forks source link

Documentation Request: How does jasmine-node actually work? #194

Open netpoetica opened 11 years ago

netpoetica commented 11 years ago

I'm curious if someone could maybe add some more verbose documentation regarding the inner workings of jasmine-node. For example, when I run

jasmine-node spec/

does this actually run my app.js file, or does it run my specs in some isolated way?

Another thing - if it's installed globally, how do you tell require about where to look for dependencies on jasmine files, and where do you put jasmine.html spec runners?

I'm sure these are likely noob concerns, but some more verbose documentation would definitely help lower the barrier to entry. If I figure out all these things before any doc updates I'll gladly contribute them myself :)

EDIT: It seems I'm not the only one having trouble with jasmine-node and Requirejs incompatabilities: https://github.com/geddesign/amd-testing http://stackoverflow.com/questions/13601016/how-to-run-jasmine-node-tests-with-requirejs/14258372#14258372

The author at http://braddickason.com/jasmine-and-nodejs-testing/ writes:

This is where, in my opinion, the jasmine-node docs fall short. Installing jasmine-node is a cinch, but you have no idea where to go from there. The first thing I figured out is that jasmine-node just gives you the simple executable that will output the results of all of your tests as well as the framework for testing, but it doesn’t give you the actual script to run the damn tests

Thanks,

tebriel commented 11 years ago

Hey Keith, Thanks, I've tried to start addressing this issue in the README.md on the beta branch. I'm not wholly familiar with requirejs itself. I've just now started learning what and how it does things so that I can better understand how @mhevery implemented the requirejs testing. From what I understand

If you install globally, that's still fine, there are two command line arguments:

These will tell jasmine-node the location of your requirejs setup file and to run using requirejs. Inside of the spec-requirejs/ folder there is a sample project that it used for testing. Check that out and see if it makes any sense to you.

Our specs.sh script runs with requirejs by calling: jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js --coffee spec-requirejs

If any of that made sense and you think you can make a more cohesive document out of it, please issue a PR on beta. I've asked @mhevery to NPM publish beta as soon as he can, but I'm planning 1.2.0 for about 2 weeks out, so it can definitely go there.

netpoetica commented 11 years ago

Hi tebriel, thanks for getting back - it's great to see the beta branch has concern for Require. Most of the time when applications of are of the scale where they need unit testing, they are also of the scale where they need dependency management/AMD so I definitely see Jasmine being used with Require a lot.

Anyhow, I have cloned the repo directly instead of downloading from npm, but I am a bit confused due to the folder and file structure. The spec-require/ folder isn't really a standalone project, but instead looks like a subdirectory to host required kloodges to get Jasmine to behave, and maybe it searches back up into the spec folder? AKA, in my own projects I would have a folder /specs and a folder /kloodge-requirejs-spec and that second folder is really like a router/bootstrap for my specs to get passed through require?

Additionally, there are JS and CoffeeScript files which have similar names, so it appears you can use one or the other, and using coffee script is optional, but when I try to run the command without --coffee, it acts as though I haven't given it enough information to run:

jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js                  path.existsSync is now called `fs.existsSync`.
USAGE: jasmine-node [--color|--noColor] [--verbose] [--coffee] directory

Options:
  --autotest         - rerun automatically the specs when a file changes
  --color            - use color coding for output
  --noColor          - do not use color coding for output
...
...

My tests do run when I use

jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js --coffee spec-requirejs

but the disparity between what is "module code" and what is "program code" makes it difficult for me to determine what I am and am not supposed to have my hands in. I'm also not sure what that "sut" file is - I know I've come across that terminology with Require, maybe from some Ruby guys talking about Unit Testing in Ruby, but I've never needed it with requirejs. It looks like maybe it's a generic shim file I shouldn't touch, but not sure exactly whether it's module code for the kloodge or program code I should edit on a project by project basis.

Also, just FYI, node is giving a warning about some fs module stuff that looks like it's deprecated:

path.existsSync is now called `fs.existsSync`.

> / find . -exec grep "path.existsSync" '{}' \; -print
        var existsSync = fs.existsSync || path.existsSync;
./lib/jasmine-node/autotest.js
        var existsSync = fs.existsSync || path.existsSync;
./lib/jasmine-node/cli.js
    var existsSync = fs.existsSync || path.existsSync;
./lib/jasmine-node/index.js
tebriel commented 11 years ago

@netpoetica Yeah, no problem. I'd like to get more into requirejs, so I'm using this as an opportunity to learn some more stuff.

jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js isn't running, I assume, because you didn't specify a spec directory. I'm still new to running jasmine-node, but I believe this is the case. your second example:

jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js --coffee spec-requirejs

calls spec-requirejs as the spec folder.

the SUT does seem to look like the shim for requirejs. I assume this will be needed so that require knows where the files are to pass them into the individual tests where they request it. I'm still not 100% on how this is all supposed to work, so I'm trying to work it out as I go.

As for the node warning, yes, I've seen this, just haven't pulled the path out/figured out why we're calling it, since it's a fallback for fs.existsSync. I assume we're just missing a reference to fs in one of those classes. I'll add an Issue for it so I don't forget. Issue #195

netpoetica commented 11 years ago

Good call! I was able to get it to run CoffeeScript-free with

jasmine-node --runWithRequireJs --requireJsSetup spec-requirejs/requirejs-setup.js spec-requirejs/

it just looks a little strange to specify the path right after another path. I will try to investigate how one could use this in their project until it becomes part of the module through NPM

tebriel commented 11 years ago

I actually use grunt with grunt-jasmine-node for my projects. It has a file watcher and a whole bunch of other modules that are really nice. Glad you were able to get it running coffee-script free. Yeah, the order of arguments doesn't matter, but it does look a little funky I guess.

I'm hoping that for 2.0.0 I'll have jasmine-node refactored enough that it will be possible to call it programmatically. grunt-jasmine-node actually builds a commandline type syntax.

netpoetica commented 11 years ago

Grunt is pretty interesting. Not sure how it will work with grunt-jasmine-node and require. Another issue to tackle is how to make sure jasmine-node allows you to run both client and server side tests on your code. For example, if I have an Account model on the server side which describes more of the DB schema and hashing, and I want to run a test on the MD5 hash to make sure it's x characters long, but then I have a public/models/Account.js which is a container for the front-end model that will be shared amongst my routes, and I want to run a test to make sure I can populate it with proper session variables.

tebriel commented 11 years ago

Hmm, a bit of beforeEach and afterEach along with some spies will allow you to mock anything that is outside of the file/function you're testing. I'd recommend going that route that way you don't have to do some sort of full-scale integration test.

davedx commented 11 years ago

I'd love to be able to call jasmine from code. I'm currently building out my own DSL based test framework that uses jasmine to run the tests, so being able to call it from code would solve lots of my current problems.

davidposin commented 11 years ago

@davedx, are you running node.js? If you are you can always spawn a child process using exec and pipe the results back to the main process.

bpytlik commented 11 years ago

Improved documentation would really help here. Like others mentioned earlier, I'm lost as to what a sut file is and why I'd need one. It would be very helpful if the example or documentation: a) explained what a sut file is needed for, would I ever need more than one for a particular spec file? b) showed an example where multiple modules were being required in the test (for example, suppose I want to test my client/server interactions, how to I require both the module that holds my client code and the module that holds my server code? Or, suppose I just need to import the fs module as well as my code because I need to read in a generated file to check that it's correct).

davidposin commented 11 years ago

@bpytlik, I can't speak to the documentation issue and I can't assist with the require.js questions but I can help regarding b. I may be able to offer insight.

Hope this offers some help.

tebriel commented 11 years ago

@Lastalas Solid advice, thanks for commenting.

RequireJS is complicated with node-jasmine right now. I'm spending time decoupling and rewriting many things to make it much easier to just drop in your main configuration file and let node-jasmine do the rest. This is a pretty serious time commitment though, so getting it done will be slower than I'd like.

prdonahue commented 11 years ago

Maybe I missed it, but I don't think one of netpoetica's question was answered: when running jasmine-node, does it fire up its own copy of node (using app.js?) or does it attempt to use what's running? The examples indicate that request.get should take a full URL (e.g., http://localhost:3000/whatever) which would seem to indicate it's designed to interact with an already running server. Of course, this all changes when combined with something like grunt, karma, etc. but I agree that as a standalone the documentation is severely lacking.

tebriel commented 11 years ago

It does not stand up a new instance of node. It DOES create a sandbox in which to load all the specs, jasmine, etc.

Also generally I try to avoid making external calls, and instead intercept them with a mock to verify that the call went out as expected, I'm not testing the server with my front-end code, that's for the server tests.

prdonahue commented 11 years ago

Thanks, just browsed through the source after posing my question to confirm that (which I should have done before asking!). Looks like I'll want to pair with something else that DOES start up node. One thing I did see in bin/jasmine-node was that it sets the environment variable to 'test':

if( !process.env.NODE_ENV ) process.env.NODE_ENV = 'test';

Here's a useful article for those with the same question: http://blog.drewolson.org/post/14684497867/.

tebriel commented 11 years ago

@prdonahue What are you trying to test? Node.js code or more Web-y front-end code? If the latter, you might want to look into karma.

prdonahue commented 11 years ago

I'm using Jasmine to test both my back-end node/express based services, as well as my front-end web code.

tebriel commented 11 years ago

Are you using require.js or some other amd-type loader for the front-end? Also, I'm starting to write a "node.js" browser for karma which acts like jasmine-node but integrates into that framework. It's just a lot of work.

We use jasmine-node to test both like you do, it works just fine. Just depends on how your module loading is done.

davidposin commented 11 years ago

I use jasmine-node for my server express-based frameworks and regular jasmine for the front end. The grunt-contrib-jasmine is a great framework for testing the front end. It will auto generate the spec runner and run against a headless browser. Jasmine-node is mostly for unit testing so it avoids trying to create integration test environments. A few items that might help:

1) If you need a stand up server, launch one with using child process. Although this won't run tests on it. 2) Use rewire. I am working on a blog post on this one, but you can use rewire to test the modules. This is a cleaner way of testing since you aren't testing express routing but the actual module function itself. 3) PhantomJs would probably do what you want to load the web server, and then you can tie node-jasmine into that....not sure how.

https://github.com/gruntjs/grunt-contrib-jasmine https://github.com/jhnns/rewire

davidposin commented 11 years ago

Also,: https://github.com/Lastalas/Jasmine-Node-Rewire-Example