Open netpoetica opened 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:
--runWithRequireJs
, loads all specs using requirejs instead of node's native require method--requireJsSetup
, file run before specs to include and configure RequireJSThese 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.
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
@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
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
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.
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.
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.
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.
@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.
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).
@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.
@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.
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.
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.
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/.
@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.
I'm using Jasmine to test both my back-end node/express based services, as well as my front-end web code.
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.
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
I'm curious if someone could maybe add some more verbose documentation regarding the inner workings of jasmine-node. For example, when I run
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:
Thanks,