Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit testing with Geddy says geddy is not defined #337

Closed
elayman opened this issue Mar 23, 2013 · 27 comments
Closed

Unit testing with Geddy says geddy is not defined #337

elayman opened this issue Mar 23, 2013 · 27 comments

Comments

@elayman
Copy link

elayman commented Mar 23, 2013

I'm running Geddy MVC Framework on Node.js on Heroku right now with a Postgres database. I can't seem to find any unit test frameworks for node.js that support Geddy. I have tried nodeunit, jasmine and a couple others but none seem to work with geddy (saying it is undefined - I think because it doesn't know how to import all of the required files).

I know Geddy provides their jake test tool but it doesn't seem to work either. It gives me this output:

ReferenceError: geddy is not defined

Any help would be greatly appreciated. Also looking for a code coverage tool that will work with the unit testing framework I get working.

Thanks!

EDIT: My tests all start with this header to import the required modules:

var assert = require('assert')
  , tests
  , Activity = geddy.model.Activity;

And the import of Activity fails with the ReferenceError above, so it never even tries my tests.

Here is a nodeunit test I wrote

var tests
  , User = geddy.model.User;

exports['addUser1'] = function (test) {
    var user = User.create({username: 'Greg',
                        password: 'MyPassword!',
                        confirmPassword: 'MyPassword!',
                        familyName: 'LastName1',
                        givenName: 'FirstName1',
                        email: 'Greg@greg.com'});
User.add(user, function (answerDict) {
    test.equal(answerDict, {'errCode': 1});
    test.done();
});
};

And the output

...../test/test-user.js:2
  , User = geddy.model.User;
           ^
ReferenceError: geddy is not defined
@MiguelMadero
Copy link
Contributor

Can you try running geddy jake test?
I have not done it, but you could also add a jake
task
to run your tests using a different
test runner.
It would look something like

task('customTests', {async: true}, function () {
  var cmds = [
    'nodeunit ./tests/'
  ];
  jake.exec(cmds, function () {
    console.log('All tests passed.');
    complete();
  }, {printStdout: true});
});

Then run geddy jake test. Geddy jake tests calls another task (env:init)
as a pre-req and that's why you get all of those undefined errors.

I played with node-jscoverage a
while ago, not with geddy, but I think it could work. Clone the repo
instead of using the one from npm.

Let me know if this works.

Miguel

@elayman
Copy link
Author

elayman commented Mar 23, 2013

So I tried your suggestion but unfortunately, I get the same issue:

...../test/test-user.js:2
  , User = geddy.model.User;
           ^
ReferenceError: geddy is not defined

@MiguelMadero
Copy link
Contributor

I'm not sure the error is related to how we run the tests. Does it work from the website?

Can you try the following:

geddy app newapp
cd newapp
geddy scaffold activity title other
geddy jake test

The scaffold generator will add a test for you that references geddy.model, that one will register your activity model. Can you try this just to discard the issue is at this layer.

@elayman
Copy link
Author

elayman commented Mar 23, 2013

Miguel, I tried your suggestion and it works.

Okay I think I got jake tests to run now. I'm not sure what I did... but I basically made a new folder called test3 and put my tests in there and changed the directory from the JakeFile to point to it. I notice the tests just run forever though (ie. I have to hit CTRL+C in order to stop the process), but it doesn't do this with the simple example test.

I get the correct output with all of my tests:

Test UserModel Add
Test Model Add Same
Test Model Add Different
Test Model Add Empty Username
Test Model Add Null Username
Test Model Add 129 Username
Test Model Add Empty Password
Test Model Add Null Password
Test Model Add 129 Password
Test Model Login Bad Credentials
All tests ran successfully

but it just sits there at the end.

@MiguelMadero
Copy link
Contributor

You might have an async test and forgot to signal that you the test
finished.

Miguel

On Sat, Mar 23, 2013 at 1:02 PM, elayman notifications@github.com wrote:

Okay I think I got jake tests to run now. I'm not sure what I did... but I
basically made a new folder called test3 and put my tests in there and
changed the directory from the JakeFile to point to it. I notice the tests
just run forever though (ie. I have to hit CTRL+C in order to stop the
process), is this normal?

I get the correct output with all of my tests:

Test UserModel Add
Test Model Add Same
Test Model Add Different
Test Model Add Empty Username
Test Model Add Null Username
Test Model Add 129 Username
Test Model Add Empty Password
Test Model Add Null Password
Test Model Add 129 Password
Test Model Login Bad Credentials
All tests ran successfully

but it just sits there at the end.


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15342683
.

@elayman
Copy link
Author

elayman commented Mar 23, 2013

I tried the node-unit jake task again and I get this output (not sure why the n's are removed):

/usr/local/lib/node_modules/geddy/node_modules/jake/lib/api.js:225
        throw errObj;
              ^
ode_modules
odeunit/lib
odeunit.js:75:37
    at _concat (/usr/local/lib
ode_modules
odeunit/deps/async.js:508:13)
    at async.forEachSeries.iterate (/usr/local/lib
ode_modules
odeunit/deps/async.js:118:13)

@elayman
Copy link
Author

elayman commented Mar 23, 2013

Ah! I forgot complete();

Thanks for your help. Any ideas on my nodeunit error?

@MiguelMadero
Copy link
Contributor

Can you try running node-unit on it's own?
Let's make sure it runs and fails because the environment isn't initialized
and then we try running it with jake.

Miguel

On Sat, Mar 23, 2013 at 1:08 PM, elayman notifications@github.com wrote:

I tried the node-unit jake task again and I get this output (not sure why
the n's are removed):

/usr/local/lib/node_modules/geddy/node_modules/jake/lib/api.js:225
throw errObj;
^
ode_modules
odeunit/lib
odeunit.js:75:37
at _concat (/usr/local/lib
ode_modules
odeunit/deps/async.js:508:13)
at async.forEachSeries.iterate (/usr/local/lib
ode_modules
odeunit/deps/async.js:118:13)


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15342794
.

@elayman
Copy link
Author

elayman commented Mar 23, 2013

Yes, I run: nodeunit test3/userTests.js

.../test3/userTests.js:3
  , User = geddy.model.User
           ^
ReferenceError: geddy is not defined

@MiguelMadero
Copy link
Contributor

That's odd. The same code works when ran with jake?
Can you explicitly exec env:init before nodeunit and see if it makes a
difference?

Miguel

On Sat, Mar 23, 2013 at 2:26 PM, elayman notifications@github.com wrote:

Yes, I run: nodeunit test3/userTests.js

.../test3/userTests.js:3
, User = geddy.model.User
^
ReferenceError: geddy is not defined


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15344115
.

@mde
Copy link
Contributor

mde commented Mar 24, 2013

Is it possible that NodeUnit is running the test code in some other process?

On Sat, Mar 23, 2013 at 6:29 PM, Miguel Madero notifications@github.comwrote:

That's odd. The same code works when ran with jake?
Can you explicitly exec env:init before nodeunit and see if it makes a
difference?

Miguel

On Sat, Mar 23, 2013 at 2:26 PM, elayman notifications@github.com
wrote:

Yes, I run: nodeunit test3/userTests.js

.../test3/userTests.js:3
, User = geddy.model.User
^
ReferenceError: geddy is not defined


Reply to this email directly or view it on GitHub<
https://github.com/mde/geddy/issues/337#issuecomment-15344115>
.


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15349546
.

@elayman
Copy link
Author

elayman commented Mar 24, 2013

I apologize for my noobiness. I am new to node.js and Geddy and therefore nodeunit as well. I tried to add the env:init to the cmds from your example Miguel, but it says command not found

task('default', {async: true}, function (params) {
  var cmds = [
    'env:init',
    'nodeunit test/test-user.js'
  ];
  jake.exec(cmds, function () {
    console.log('All tests passed.');
    complete();
  }, {printStdout: true});
});

Error: /bin/sh: env:init: command not found

@MiguelMadero
Copy link
Contributor

@mde is right. Nodeunit is using a different process, so this solution won't work. Even if we initialized the env in jake, we're starting a new process, hence new memory, new domain and undefined variables.

Now, just as a reference, if we wanted to initialized the environment before we would run it as a jake task, not as another command. I was on the phone and couldn't send a link, but you can have a look at the jake docs for for further reference. To execute another jake task would run jake.Task['env:init'].invoke();. Keep in mind that this won't work since running nodeunit creates a new process. Also consider this shouldn't be needed if you run geddy jake, since geddy will do exactly this, run env:init before any other jake task.

Now a couple of solutions are:

  • Call env:init from nodeunit. You could either require jake, point it to the geddy Jakefile and call require init. Or, just use the code from the env:init task. Note: we should probably refactor this so it can be used easily outside of jake by just calling something require('geddy').init()
    var cfg = {};
    if (process.env.environment) {
      cfg.environment = process.env.environment;
    }

    jake.addListener('complete', function (e) {
      jake.Task['env:cleanup'].invoke();
    });

    geddy.config = require('../lib/config').readConfig(cfg);
    geddy.model = require('model');

    require('../lib/init').init(geddy, function () {
      complete();
    });

Have a look at moduleStart on nodeunit. Looks like that would be the place to initialize the geddy environment.

  • Call nodeunit inside the jake process, instead of creating a new process.
    You can create a new task in jake to run nodeunit tests. Inside instead of using the execute command as I suggested earlier, require nodeunit as described on the nodeunit docs:
var reporter = require('nodeunit').reporters.default;
reporter.run(['test']);

I've not had a chance to test any of this, but I hope this gives you some pointers. Let me know how it goes. We will have to do some changes to geddy to make this easier and add some docs. It's always good to play nice with alternative options, and jake isn't really shining as a test runner so this is an important category.

@elayman
Copy link
Author

elayman commented Mar 25, 2013

So I tried to mess around with this today but couldn't get it working. It seems running the reporter.run still initializes a new process because the behavior is the same as calling exec nodeunit.

EDIT: I put the geddy init code in nodeunit/lib/reporters/default.js in the moduleStart method. Unfortunately, it must load the test file before it runs the moduleStart, so I had to create a new test file (with name earlier in the alphabet so it gets loaded first) with a fake test in it because my references to Geddy in my test file crashed the process. I also had to change some of the relative locations to access the geddy module. However, it seems to get to /geddy/lib/init/model.js:55:20 and errors because the require('utilities') doesn't seem to work correctly TypeError: Object #<Object> has no method '_getConstructorsFromDirectory'

EDIT2: I was able to fix that error by adding geddy.utils = require('../../../geddy/lib/utils'); to my init code. But now It says Error: Model Activity did not get registered properly. from geddy/lib/init/model.js:70:15

And unfortunately, the comment above this line doesn't help me much 😃 // If the model doesn't exist, something is fucked up

geddy = require('../../../geddy/lib/geddy');
            var cfg = {};
            if (process.env.environment) {
              cfg.environment = process.env.environment;
            }
            jake.addListener('complete', function (e) {
              jake.Task['env:cleanup'].invoke();
            });
            geddy.utils = require('../../../geddy/lib/utils');
            geddy.config = require('../../../geddy/lib/config').readConfig(cfg);
            geddy.model = require('../../../geddy/lib/model');
            require('../../../geddy/lib/init').init(geddy, function () {
              complete();
            });

@MiguelMadero
Copy link
Contributor

I don't have experience with nodeunit and I just got that from the docs.
It's odd that logging isn't working. Can you try a different test runner or
are you sold on nodeunit?

Miguel

On Mon, Mar 25, 2013 at 11:36 AM, elayman notifications@github.com wrote:

So I tried to mess around with this today with little luck. It seems
running the reporter.run still initializes a new process because the
behavior is the same as calling exec nodeunit.

I also tried to add the code you provided (from the init task) in the
nodeunit/lib/reporters/default.js in moduleStart: function (name) { but
it doesn't seem to affect anything. I also tried logging to console in a
bunch of places in the nodeunit module but none of them output (maybe they
have logging turned off?). Is there a different moduleStart method to
which you were referring?

Thanks again for your help!


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15408342
.

@elayman
Copy link
Author

elayman commented Mar 26, 2013

I am not opposed to another testing framework, however I believe I will have similar issues with others won't I? Do you know of a test runner that doesn't use another process?

@MiguelMadero
Copy link
Contributor

Sorry, that's an area I'm not familiar with. I'm guessing that running it
from your code others won't start another process.

Miguel

On Mon, Mar 25, 2013 at 10:59 PM, elayman notifications@github.com wrote:

I am not opposed to another testing framework, however I believe I will
have similar issues with others won't I? Do you know of a test runner that
doesn't use another process?


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15441186
.

@elayman
Copy link
Author

elayman commented Mar 26, 2013

Thanks for all of your guidance @MiguelMadero. I found a jakefile for running Mocha here: https://gist.github.com/BryanDonovan/5022389

I will try to use Mocha since it seems to be another good testing framework.

@MiguelMadero
Copy link
Contributor

Awesome, its great you found it. Maybe you can help us creating a testing
wiki page to make this easier for the next one :)

I'll have a look once I finish this trip.

Thanks
On 26/03/2013 12:15 PM, "elayman" notifications@github.com wrote:

Thanks for all of your guidance @MiguelMaderohttps://github.com/MiguelMadero.
I found a jakefile for running Mocha here:
https://gist.github.com/BryanDonovan/5022389

I will try to use Mocha since it seems to be another good testing
framework.


Reply to this email directly or view it on GitHubhttps://github.com//issues/337#issuecomment-15476228
.

@elayman
Copy link
Author

elayman commented Mar 27, 2013

Done: https://github.com/mde/geddy/wiki/Unit-Testing-With-Geddy

Feel free to edit or mention things I should add!

@mde
Copy link
Contributor

mde commented Mar 27, 2013

Fantastic! I know this will help a lot of people out.

@elayman
Copy link
Author

elayman commented Mar 28, 2013

Since this is somewhat related (I had mentioned I wanted to use a code coverage tool), do you know if I can do something similar to this post to run node-jscoverage, (ie. flatten the app directory and use instinct, or will Geddy complain)?

"add instinct.js that consolidated all my models, controllers, middleware and exported them from one place. Then elsewhere in my project anytime I needed a model, controller or middleware I just required that main instinct module like so:

var instinct = require('./instinct');

Then I added an index.js file at the project root that exports either lib/instinct or lib-cov/instinct depending on the INSTINCT_COV environment variable (which we'll set in our MakeFile)"

Original link: http://brianstoner.com/blog/testing-in-nodejs-with-mocha/

@elayman
Copy link
Author

elayman commented Mar 31, 2013

@MiguelMadero - do you know if there's a config in geddy where it chooses the app/ directory so I can change it to app-cov/ when I'm using jscoverage?

@larzconwell
Copy link
Contributor

@elayman No there isn't, although you could just symlink app-cov to app.

@mde
Copy link
Contributor

mde commented Mar 31, 2013

There is an option to set the app directory when running the server (-g/--geddy-root), but it only works when running the server. (geddy jake just does passthrough to Jake, so most of the CLI options don't actually do anything.)

Another alternative would be to have a Jake task that you use a a prerequisite that does process.cwd to a desired directory before running your tests.

@elayman
Copy link
Author

elayman commented Apr 26, 2013

I followed @mde 's advice and created a copy of the directory before covering the code. Then I change directory and run the tests.

Here is my wiki with link to my code: https://github.com/mde/geddy/wiki/Unit-Testing-&-Code-Coverage-With-Geddy

@elayman elayman closed this as completed Apr 26, 2013
@mde
Copy link
Contributor

mde commented Apr 27, 2013

Nice. Thanks for the wiki link. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants