Re: [Node 101] Part 1: Small Modules
I've encountered this myself in personal projects. With tests you will catch it early of course, but I'm not sure if there is a linter/tool that will catch this early on to save grief later On Mon, Dec 16, 2013 at 4:49 AM, Patrick Mueller wrote: > What I've learned from this is to be careful when you use `module.exports > =`. > > It doesn't come up much, because it's only a problem (I think) when there > is some mutual recursion in your require() trees. I've done this to myself > when building packages where I was exporting functions via `module.exports > =` as a common pattern, and then "crossed the paths" somewhere. > > Note that this is a dev-time problem, and not a run-time problem. Assuming > you are testing all your code, you will find problems with this pattern > VERY EARLY. So, it's nothing to be scared of or outlaw entirely. It's > never going to "pop up" unexpectedly at runtime. > > It is, unfortunately, a bit of a mysterious bug, when it does happen. So I > wanted others to be aware of this one weird problem with the pattern. > > > > On Sun, Dec 15, 2013 at 8:08 PM, Brian LeRoux wrote: > > > Super interesting, I am surprised this doesn't come up more often really. > > > > I suppose the moral of the story is to avoid executing code in your > modules > > outside of the scope of things you are exporting. > > > > > > On Mon, Dec 16, 2013 at 3:46 AM, Patrick Mueller > > wrote: > > > > > The big problem with exporting functions - or exporting anything by > using > > > `module.exports =` style of exporting - is recursive require problem. > I > > > couldn't quickly find any ref to this on the web, so did a little gist: > > > https://gist.github.com/pmuellr/7975152 > > > > > > > > > On Thu, Dec 12, 2013 at 7:37 PM, Brian LeRoux wrote: > > > > > > > Oh interesting. I can see what you mean though I think the only > thing I > > > > should know about the output is the return value. (In your case, > just a > > > > test for 'done'.) The behavior of the module is super important of > > > course. > > > > In the small modules philosophy the foo, bar.method, and baz would > have > > > > thier own tests for interface/output to satisfy the case you > describe. > > > > > > > > Again, IT DEPENDS! The rimraf example is a perfect case for what you > > > > describe. > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner > > wrote: > > > > > > > > > It depends what you define as outputs. > > > > > > > > > > in a given module: > > > > > > > > > > var foo = require('foo'), bar = require('bar'), baz = > require('baz'); > > > > > > > > > > module.exports = function(a, b) { > > > > > foo(3); > > > > > bar.method(a); > > > > > baz(b); > > > > > > > > > >return "done"; > > > > > } > > > > > > > > > > I have always counted the calls to foo, bar and baz as output that > > > needs > > > > to > > > > > be tested. This would produce a spec like: > > > > > > > > > > "when calling this module": > > > > >"it calls foo with 3" > > > > >"it calls bar.method with a" > > > > >"it calls baz with b" > > > > >"it returns done" > > > > > > > > > > It is just easier to mock bar.method then foo > > > > > > > > > > ie: > > > > > > > > > > var rewire = require('rewire'); > > > > > var example = rewire('example'); //NOTE: rewire rather then > > require > > > > > example.__set__('foo', jasmine.createSpy()); > > > > > > > > > > vrs: > > > > > > > > > > var example = require('example'); > > > > > var bar = require('bar'); > > > > > spyOn(bar, "method"); > > > > > > > > > > I came across this problem when using one of Isaac's modules > (rimraf > > > [1]) > > > > > where I obviously didn't want to call that in a unit test from my > > > module > > > > > but I need to mock it out. Rewire was the only way I could. > > > > > > > > > > [1] - https://github.com/isaacs/rimraf > > > > > > > > > > > > > > > > > > > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > > > > > > > > > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > > > > > > programming. The answer is ALWAYS 'it depends'. No absolutes in > the > > > sea > > > > > of > > > > > > change. > > > > > > > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux > wrote: > > > > > > > > > > > > > Maybe. Have a look at Substack's code and you'll see he has no > > > > trouble > > > > > > > testing. The reason being he tests interfaces and outputs > instead > > > of > > > > > > > implementations. That will be another Node 101! > > > > > > > > > > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner < > gtan...@gmail.com > > > > > > > > wrote: > > > > > > > > > > > > > >> I also agree with this except for returning a function from > > > > > > >> module.exports. > > > > > > >> > > > > > > >> It is possible but makes mocking much much harder for testing. > > > > > > >> > > > > > > >> think of: > > > > > > >> > > > > > > >> > > > > > > >> var foo = require('foo'); > > > > > > >> > > > >
Re: [Node 101] Part 1: Small Modules
What I've learned from this is to be careful when you use `module.exports =`. It doesn't come up much, because it's only a problem (I think) when there is some mutual recursion in your require() trees. I've done this to myself when building packages where I was exporting functions via `module.exports =` as a common pattern, and then "crossed the paths" somewhere. Note that this is a dev-time problem, and not a run-time problem. Assuming you are testing all your code, you will find problems with this pattern VERY EARLY. So, it's nothing to be scared of or outlaw entirely. It's never going to "pop up" unexpectedly at runtime. It is, unfortunately, a bit of a mysterious bug, when it does happen. So I wanted others to be aware of this one weird problem with the pattern. On Sun, Dec 15, 2013 at 8:08 PM, Brian LeRoux wrote: > Super interesting, I am surprised this doesn't come up more often really. > > I suppose the moral of the story is to avoid executing code in your modules > outside of the scope of things you are exporting. > > > On Mon, Dec 16, 2013 at 3:46 AM, Patrick Mueller > wrote: > > > The big problem with exporting functions - or exporting anything by using > > `module.exports =` style of exporting - is recursive require problem. I > > couldn't quickly find any ref to this on the web, so did a little gist: > > https://gist.github.com/pmuellr/7975152 > > > > > > On Thu, Dec 12, 2013 at 7:37 PM, Brian LeRoux wrote: > > > > > Oh interesting. I can see what you mean though I think the only thing I > > > should know about the output is the return value. (In your case, just a > > > test for 'done'.) The behavior of the module is super important of > > course. > > > In the small modules philosophy the foo, bar.method, and baz would have > > > thier own tests for interface/output to satisfy the case you describe. > > > > > > Again, IT DEPENDS! The rimraf example is a perfect case for what you > > > describe. > > > > > > > > > On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner > wrote: > > > > > > > It depends what you define as outputs. > > > > > > > > in a given module: > > > > > > > > var foo = require('foo'), bar = require('bar'), baz = require('baz'); > > > > > > > > module.exports = function(a, b) { > > > > foo(3); > > > > bar.method(a); > > > > baz(b); > > > > > > > >return "done"; > > > > } > > > > > > > > I have always counted the calls to foo, bar and baz as output that > > needs > > > to > > > > be tested. This would produce a spec like: > > > > > > > > "when calling this module": > > > >"it calls foo with 3" > > > >"it calls bar.method with a" > > > >"it calls baz with b" > > > >"it returns done" > > > > > > > > It is just easier to mock bar.method then foo > > > > > > > > ie: > > > > > > > > var rewire = require('rewire'); > > > > var example = rewire('example'); //NOTE: rewire rather then > require > > > > example.__set__('foo', jasmine.createSpy()); > > > > > > > > vrs: > > > > > > > > var example = require('example'); > > > > var bar = require('bar'); > > > > spyOn(bar, "method"); > > > > > > > > I came across this problem when using one of Isaac's modules (rimraf > > [1]) > > > > where I obviously didn't want to call that in a unit test from my > > module > > > > but I need to mock it out. Rewire was the only way I could. > > > > > > > > [1] - https://github.com/isaacs/rimraf > > > > > > > > > > > > > > > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > > > > > > > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > > > > > programming. The answer is ALWAYS 'it depends'. No absolutes in the > > sea > > > > of > > > > > change. > > > > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > > > > > > > > > > > Maybe. Have a look at Substack's code and you'll see he has no > > > trouble > > > > > > testing. The reason being he tests interfaces and outputs instead > > of > > > > > > implementations. That will be another Node 101! > > > > > > > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner > > > > > wrote: > > > > > > > > > > > >> I also agree with this except for returning a function from > > > > > >> module.exports. > > > > > >> > > > > > >> It is possible but makes mocking much much harder for testing. > > > > > >> > > > > > >> think of: > > > > > >> > > > > > >> > > > > > >> var foo = require('foo'); > > > > > >> > > > > > >> module.exports = { > > > > > >> awesome: function (a) { > > > > > >> foo(a+1); > > > > > >>} > > > > > >> }; > > > > > >> > > > > > >> It is kind of awkward to test this module's use of the foo > module. > > > It > > > > > can > > > > > >> be done with rewire [1] but is a little awkward. > > > > > >> > > > > > >> If foo was designed where it exported an object literal with > > > functions > > > > > it > > > > > >> would be much easier to mock: > > > > > >> > > > > > >> var foo = require('foo'); > > > > > >> > > > > > >> module.expor
Re: [Node 101] Part 1: Small Modules
More fun on the topic. http://www.richardrodger.com/monolithic-nodejs#.Uq6k4WQW2LB Love the thinking spreading to hypermedia w/ the term 'microservices'. Not directly in our wheelhouse but related. On Mon, Dec 16, 2013 at 12:08 PM, Brian LeRoux wrote: > Super interesting, I am surprised this doesn't come up more often really. > > I suppose the moral of the story is to avoid executing code in your > modules outside of the scope of things you are exporting. > > > On Mon, Dec 16, 2013 at 3:46 AM, Patrick Mueller wrote: > >> The big problem with exporting functions - or exporting anything by using >> `module.exports =` style of exporting - is recursive require problem. I >> couldn't quickly find any ref to this on the web, so did a little gist: >> https://gist.github.com/pmuellr/7975152 >> >> >> On Thu, Dec 12, 2013 at 7:37 PM, Brian LeRoux wrote: >> >> > Oh interesting. I can see what you mean though I think the only thing I >> > should know about the output is the return value. (In your case, just a >> > test for 'done'.) The behavior of the module is super important of >> course. >> > In the small modules philosophy the foo, bar.method, and baz would have >> > thier own tests for interface/output to satisfy the case you describe. >> > >> > Again, IT DEPENDS! The rimraf example is a perfect case for what you >> > describe. >> > >> > >> > On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner >> wrote: >> > >> > > It depends what you define as outputs. >> > > >> > > in a given module: >> > > >> > > var foo = require('foo'), bar = require('bar'), baz = require('baz'); >> > > >> > > module.exports = function(a, b) { >> > > foo(3); >> > > bar.method(a); >> > > baz(b); >> > > >> > >return "done"; >> > > } >> > > >> > > I have always counted the calls to foo, bar and baz as output that >> needs >> > to >> > > be tested. This would produce a spec like: >> > > >> > > "when calling this module": >> > >"it calls foo with 3" >> > >"it calls bar.method with a" >> > >"it calls baz with b" >> > >"it returns done" >> > > >> > > It is just easier to mock bar.method then foo >> > > >> > > ie: >> > > >> > > var rewire = require('rewire'); >> > > var example = rewire('example'); //NOTE: rewire rather then >> require >> > > example.__set__('foo', jasmine.createSpy()); >> > > >> > > vrs: >> > > >> > > var example = require('example'); >> > > var bar = require('bar'); >> > > spyOn(bar, "method"); >> > > >> > > I came across this problem when using one of Isaac's modules (rimraf >> [1]) >> > > where I obviously didn't want to call that in a unit test from my >> module >> > > but I need to mock it out. Rewire was the only way I could. >> > > >> > > [1] - https://github.com/isaacs/rimraf >> > > >> > > >> > > >> > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: >> > > >> > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its >> > > > programming. The answer is ALWAYS 'it depends'. No absolutes in the >> sea >> > > of >> > > > change. >> > > > >> > > > >> > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: >> > > > >> > > > > Maybe. Have a look at Substack's code and you'll see he has no >> > trouble >> > > > > testing. The reason being he tests interfaces and outputs instead >> of >> > > > > implementations. That will be another Node 101! >> > > > > >> > > > > >> > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner >> > > wrote: >> > > > > >> > > > >> I also agree with this except for returning a function from >> > > > >> module.exports. >> > > > >> >> > > > >> It is possible but makes mocking much much harder for testing. >> > > > >> >> > > > >> think of: >> > > > >> >> > > > >> >> > > > >> var foo = require('foo'); >> > > > >> >> > > > >> module.exports = { >> > > > >> awesome: function (a) { >> > > > >> foo(a+1); >> > > > >>} >> > > > >> }; >> > > > >> >> > > > >> It is kind of awkward to test this module's use of the foo >> module. >> > It >> > > > can >> > > > >> be done with rewire [1] but is a little awkward. >> > > > >> >> > > > >> If foo was designed where it exported an object literal with >> > functions >> > > > it >> > > > >> would be much easier to mock: >> > > > >> >> > > > >> var foo = require('foo'); >> > > > >> >> > > > >> module.exports = { >> > > > >> awesome: function (a) { >> > > > >> foo.bar(a+1); >> > > > >>} >> > > > >> }; >> > > > >> >> > > > >> it("calls foo.bar", function () { >> > > > >> var foo = require('foo'); >> > > > >> spyOn(foo, "bar"); >> > > > >> }); >> > > > >> >> > > > >> Just my 2 cents from a testing perspective. >> > > > >> >> > > > >> >> > > > >> [1] - https://github.com/jhnns/rewire >> > > > >> >> > > > >> >> > > > >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux >> wrote: >> > > > >> >> > > > >> > Create modules that are the smallest possible unit of code. >> Less >> > > code >> > > > is >> > > > >> > fast code. Faster to write. Faster to maintain. Faster to >> test. On >> > >
Re: [Node 101] Part 1: Small Modules
Super interesting, I am surprised this doesn't come up more often really. I suppose the moral of the story is to avoid executing code in your modules outside of the scope of things you are exporting. On Mon, Dec 16, 2013 at 3:46 AM, Patrick Mueller wrote: > The big problem with exporting functions - or exporting anything by using > `module.exports =` style of exporting - is recursive require problem. I > couldn't quickly find any ref to this on the web, so did a little gist: > https://gist.github.com/pmuellr/7975152 > > > On Thu, Dec 12, 2013 at 7:37 PM, Brian LeRoux wrote: > > > Oh interesting. I can see what you mean though I think the only thing I > > should know about the output is the return value. (In your case, just a > > test for 'done'.) The behavior of the module is super important of > course. > > In the small modules philosophy the foo, bar.method, and baz would have > > thier own tests for interface/output to satisfy the case you describe. > > > > Again, IT DEPENDS! The rimraf example is a perfect case for what you > > describe. > > > > > > On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner wrote: > > > > > It depends what you define as outputs. > > > > > > in a given module: > > > > > > var foo = require('foo'), bar = require('bar'), baz = require('baz'); > > > > > > module.exports = function(a, b) { > > > foo(3); > > > bar.method(a); > > > baz(b); > > > > > >return "done"; > > > } > > > > > > I have always counted the calls to foo, bar and baz as output that > needs > > to > > > be tested. This would produce a spec like: > > > > > > "when calling this module": > > >"it calls foo with 3" > > >"it calls bar.method with a" > > >"it calls baz with b" > > >"it returns done" > > > > > > It is just easier to mock bar.method then foo > > > > > > ie: > > > > > > var rewire = require('rewire'); > > > var example = rewire('example'); //NOTE: rewire rather then require > > > example.__set__('foo', jasmine.createSpy()); > > > > > > vrs: > > > > > > var example = require('example'); > > > var bar = require('bar'); > > > spyOn(bar, "method"); > > > > > > I came across this problem when using one of Isaac's modules (rimraf > [1]) > > > where I obviously didn't want to call that in a unit test from my > module > > > but I need to mock it out. Rewire was the only way I could. > > > > > > [1] - https://github.com/isaacs/rimraf > > > > > > > > > > > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > > > > > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > > > > programming. The answer is ALWAYS 'it depends'. No absolutes in the > sea > > > of > > > > change. > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > > > > > > > > > Maybe. Have a look at Substack's code and you'll see he has no > > trouble > > > > > testing. The reason being he tests interfaces and outputs instead > of > > > > > implementations. That will be another Node 101! > > > > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner > > > wrote: > > > > > > > > > >> I also agree with this except for returning a function from > > > > >> module.exports. > > > > >> > > > > >> It is possible but makes mocking much much harder for testing. > > > > >> > > > > >> think of: > > > > >> > > > > >> > > > > >> var foo = require('foo'); > > > > >> > > > > >> module.exports = { > > > > >> awesome: function (a) { > > > > >> foo(a+1); > > > > >>} > > > > >> }; > > > > >> > > > > >> It is kind of awkward to test this module's use of the foo module. > > It > > > > can > > > > >> be done with rewire [1] but is a little awkward. > > > > >> > > > > >> If foo was designed where it exported an object literal with > > functions > > > > it > > > > >> would be much easier to mock: > > > > >> > > > > >> var foo = require('foo'); > > > > >> > > > > >> module.exports = { > > > > >> awesome: function (a) { > > > > >> foo.bar(a+1); > > > > >>} > > > > >> }; > > > > >> > > > > >> it("calls foo.bar", function () { > > > > >> var foo = require('foo'); > > > > >> spyOn(foo, "bar"); > > > > >> }); > > > > >> > > > > >> Just my 2 cents from a testing perspective. > > > > >> > > > > >> > > > > >> [1] - https://github.com/jhnns/rewire > > > > >> > > > > >> > > > > >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > > > > >> > > > > >> > Create modules that are the smallest possible unit of code. Less > > > code > > > > is > > > > >> > fast code. Faster to write. Faster to maintain. Faster to test. > On > > > the > > > > >> > extreme end characters in the Node community such as Substack > > > > advocate a > > > > >> > single function per module definition. > > > > >> > > > > > >> > module.exports = function() { > > > > >> > // my logic here > > > > >> > } > > > > >> > > > > > >> > This is kind of extreme and not always possible but a good > > practice > > > > >> > nonetheless. The idea is not new. Its a part of the UNIX > > ph
Re: [Node 101] Part 1: Small Modules
The big problem with exporting functions - or exporting anything by using `module.exports =` style of exporting - is recursive require problem. I couldn't quickly find any ref to this on the web, so did a little gist: https://gist.github.com/pmuellr/7975152 On Thu, Dec 12, 2013 at 7:37 PM, Brian LeRoux wrote: > Oh interesting. I can see what you mean though I think the only thing I > should know about the output is the return value. (In your case, just a > test for 'done'.) The behavior of the module is super important of course. > In the small modules philosophy the foo, bar.method, and baz would have > thier own tests for interface/output to satisfy the case you describe. > > Again, IT DEPENDS! The rimraf example is a perfect case for what you > describe. > > > On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner wrote: > > > It depends what you define as outputs. > > > > in a given module: > > > > var foo = require('foo'), bar = require('bar'), baz = require('baz'); > > > > module.exports = function(a, b) { > > foo(3); > > bar.method(a); > > baz(b); > > > >return "done"; > > } > > > > I have always counted the calls to foo, bar and baz as output that needs > to > > be tested. This would produce a spec like: > > > > "when calling this module": > >"it calls foo with 3" > >"it calls bar.method with a" > >"it calls baz with b" > >"it returns done" > > > > It is just easier to mock bar.method then foo > > > > ie: > > > > var rewire = require('rewire'); > > var example = rewire('example'); //NOTE: rewire rather then require > > example.__set__('foo', jasmine.createSpy()); > > > > vrs: > > > > var example = require('example'); > > var bar = require('bar'); > > spyOn(bar, "method"); > > > > I came across this problem when using one of Isaac's modules (rimraf [1]) > > where I obviously didn't want to call that in a unit test from my module > > but I need to mock it out. Rewire was the only way I could. > > > > [1] - https://github.com/isaacs/rimraf > > > > > > > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > > > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > > > programming. The answer is ALWAYS 'it depends'. No absolutes in the sea > > of > > > change. > > > > > > > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > > > > > > > Maybe. Have a look at Substack's code and you'll see he has no > trouble > > > > testing. The reason being he tests interfaces and outputs instead of > > > > implementations. That will be another Node 101! > > > > > > > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner > > wrote: > > > > > > > >> I also agree with this except for returning a function from > > > >> module.exports. > > > >> > > > >> It is possible but makes mocking much much harder for testing. > > > >> > > > >> think of: > > > >> > > > >> > > > >> var foo = require('foo'); > > > >> > > > >> module.exports = { > > > >> awesome: function (a) { > > > >> foo(a+1); > > > >>} > > > >> }; > > > >> > > > >> It is kind of awkward to test this module's use of the foo module. > It > > > can > > > >> be done with rewire [1] but is a little awkward. > > > >> > > > >> If foo was designed where it exported an object literal with > functions > > > it > > > >> would be much easier to mock: > > > >> > > > >> var foo = require('foo'); > > > >> > > > >> module.exports = { > > > >> awesome: function (a) { > > > >> foo.bar(a+1); > > > >>} > > > >> }; > > > >> > > > >> it("calls foo.bar", function () { > > > >> var foo = require('foo'); > > > >> spyOn(foo, "bar"); > > > >> }); > > > >> > > > >> Just my 2 cents from a testing perspective. > > > >> > > > >> > > > >> [1] - https://github.com/jhnns/rewire > > > >> > > > >> > > > >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > > > >> > > > >> > Create modules that are the smallest possible unit of code. Less > > code > > > is > > > >> > fast code. Faster to write. Faster to maintain. Faster to test. On > > the > > > >> > extreme end characters in the Node community such as Substack > > > advocate a > > > >> > single function per module definition. > > > >> > > > > >> > module.exports = function() { > > > >> > // my logic here > > > >> > } > > > >> > > > > >> > This is kind of extreme and not always possible but a good > practice > > > >> > nonetheless. The idea is not new. Its a part of the UNIX > philosophy: > > > "do > > > >> > one thing well" coined by Doug Mcilroy. [1] > > > >> > > > > >> > It can help you make code that looks like this [2] into this [3]. > > > >> > > > > >> > > > > >> > > > > >> > [1] > > > http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html > > > >> > [2] > > > >> > > > > >> > > > > >> > > > > > > https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js > > > >> > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js > > > >> > > > > >> > > > > > > > > > > > > > > --
Re: [Node 101] Part 1: Small Modules
Oh interesting. I can see what you mean though I think the only thing I should know about the output is the return value. (In your case, just a test for 'done'.) The behavior of the module is super important of course. In the small modules philosophy the foo, bar.method, and baz would have thier own tests for interface/output to satisfy the case you describe. Again, IT DEPENDS! The rimraf example is a perfect case for what you describe. On Fri, Dec 13, 2013 at 10:59 AM, Gord Tanner wrote: > It depends what you define as outputs. > > in a given module: > > var foo = require('foo'), bar = require('bar'), baz = require('baz'); > > module.exports = function(a, b) { > foo(3); > bar.method(a); > baz(b); > >return "done"; > } > > I have always counted the calls to foo, bar and baz as output that needs to > be tested. This would produce a spec like: > > "when calling this module": >"it calls foo with 3" >"it calls bar.method with a" >"it calls baz with b" >"it returns done" > > It is just easier to mock bar.method then foo > > ie: > > var rewire = require('rewire'); > var example = rewire('example'); //NOTE: rewire rather then require > example.__set__('foo', jasmine.createSpy()); > > vrs: > > var example = require('example'); > var bar = require('bar'); > spyOn(bar, "method"); > > I came across this problem when using one of Isaac's modules (rimraf [1]) > where I obviously didn't want to call that in a unit test from my module > but I need to mock it out. Rewire was the only way I could. > > [1] - https://github.com/isaacs/rimraf > > > > On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > > > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > > programming. The answer is ALWAYS 'it depends'. No absolutes in the sea > of > > change. > > > > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > > > > > Maybe. Have a look at Substack's code and you'll see he has no trouble > > > testing. The reason being he tests interfaces and outputs instead of > > > implementations. That will be another Node 101! > > > > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner > wrote: > > > > > >> I also agree with this except for returning a function from > > >> module.exports. > > >> > > >> It is possible but makes mocking much much harder for testing. > > >> > > >> think of: > > >> > > >> > > >> var foo = require('foo'); > > >> > > >> module.exports = { > > >> awesome: function (a) { > > >> foo(a+1); > > >>} > > >> }; > > >> > > >> It is kind of awkward to test this module's use of the foo module. It > > can > > >> be done with rewire [1] but is a little awkward. > > >> > > >> If foo was designed where it exported an object literal with functions > > it > > >> would be much easier to mock: > > >> > > >> var foo = require('foo'); > > >> > > >> module.exports = { > > >> awesome: function (a) { > > >> foo.bar(a+1); > > >>} > > >> }; > > >> > > >> it("calls foo.bar", function () { > > >> var foo = require('foo'); > > >> spyOn(foo, "bar"); > > >> }); > > >> > > >> Just my 2 cents from a testing perspective. > > >> > > >> > > >> [1] - https://github.com/jhnns/rewire > > >> > > >> > > >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > > >> > > >> > Create modules that are the smallest possible unit of code. Less > code > > is > > >> > fast code. Faster to write. Faster to maintain. Faster to test. On > the > > >> > extreme end characters in the Node community such as Substack > > advocate a > > >> > single function per module definition. > > >> > > > >> > module.exports = function() { > > >> > // my logic here > > >> > } > > >> > > > >> > This is kind of extreme and not always possible but a good practice > > >> > nonetheless. The idea is not new. Its a part of the UNIX philosophy: > > "do > > >> > one thing well" coined by Doug Mcilroy. [1] > > >> > > > >> > It can help you make code that looks like this [2] into this [3]. > > >> > > > >> > > > >> > > > >> > [1] > > http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html > > >> > [2] > > >> > > > >> > > > >> > > > https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js > > >> > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js > > >> > > > >> > > > > > > > > >
Re: [Node 101] Part 1: Small Modules
It depends what you define as outputs. in a given module: var foo = require('foo'), bar = require('bar'), baz = require('baz'); module.exports = function(a, b) { foo(3); bar.method(a); baz(b); return "done"; } I have always counted the calls to foo, bar and baz as output that needs to be tested. This would produce a spec like: "when calling this module": "it calls foo with 3" "it calls bar.method with a" "it calls baz with b" "it returns done" It is just easier to mock bar.method then foo ie: var rewire = require('rewire'); var example = rewire('example'); //NOTE: rewire rather then require example.__set__('foo', jasmine.createSpy()); vrs: var example = require('example'); var bar = require('bar'); spyOn(bar, "method"); I came across this problem when using one of Isaac's modules (rimraf [1]) where I obviously didn't want to call that in a unit test from my module but I need to mock it out. Rewire was the only way I could. [1] - https://github.com/isaacs/rimraf On Thu, Dec 12, 2013 at 6:37 PM, Brian LeRoux wrote: > ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its > programming. The answer is ALWAYS 'it depends'. No absolutes in the sea of > change. > > > On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > > > Maybe. Have a look at Substack's code and you'll see he has no trouble > > testing. The reason being he tests interfaces and outputs instead of > > implementations. That will be another Node 101! > > > > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner wrote: > > > >> I also agree with this except for returning a function from > >> module.exports. > >> > >> It is possible but makes mocking much much harder for testing. > >> > >> think of: > >> > >> > >> var foo = require('foo'); > >> > >> module.exports = { > >> awesome: function (a) { > >> foo(a+1); > >>} > >> }; > >> > >> It is kind of awkward to test this module's use of the foo module. It > can > >> be done with rewire [1] but is a little awkward. > >> > >> If foo was designed where it exported an object literal with functions > it > >> would be much easier to mock: > >> > >> var foo = require('foo'); > >> > >> module.exports = { > >> awesome: function (a) { > >> foo.bar(a+1); > >>} > >> }; > >> > >> it("calls foo.bar", function () { > >> var foo = require('foo'); > >> spyOn(foo, "bar"); > >> }); > >> > >> Just my 2 cents from a testing perspective. > >> > >> > >> [1] - https://github.com/jhnns/rewire > >> > >> > >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > >> > >> > Create modules that are the smallest possible unit of code. Less code > is > >> > fast code. Faster to write. Faster to maintain. Faster to test. On the > >> > extreme end characters in the Node community such as Substack > advocate a > >> > single function per module definition. > >> > > >> > module.exports = function() { > >> > // my logic here > >> > } > >> > > >> > This is kind of extreme and not always possible but a good practice > >> > nonetheless. The idea is not new. Its a part of the UNIX philosophy: > "do > >> > one thing well" coined by Doug Mcilroy. [1] > >> > > >> > It can help you make code that looks like this [2] into this [3]. > >> > > >> > > >> > > >> > [1] > http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html > >> > [2] > >> > > >> > > >> > https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js > >> > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js > >> > > >> > > > > >
Re: [Node 101] Part 1: Small Modules
ALSO: lets avoid using terms like 'I agree' or 'I disagree'. Its programming. The answer is ALWAYS 'it depends'. No absolutes in the sea of change. On Fri, Dec 13, 2013 at 10:34 AM, Brian LeRoux wrote: > Maybe. Have a look at Substack's code and you'll see he has no trouble > testing. The reason being he tests interfaces and outputs instead of > implementations. That will be another Node 101! > > > On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner wrote: > >> I also agree with this except for returning a function from >> module.exports. >> >> It is possible but makes mocking much much harder for testing. >> >> think of: >> >> >> var foo = require('foo'); >> >> module.exports = { >> awesome: function (a) { >> foo(a+1); >>} >> }; >> >> It is kind of awkward to test this module's use of the foo module. It can >> be done with rewire [1] but is a little awkward. >> >> If foo was designed where it exported an object literal with functions it >> would be much easier to mock: >> >> var foo = require('foo'); >> >> module.exports = { >> awesome: function (a) { >> foo.bar(a+1); >>} >> }; >> >> it("calls foo.bar", function () { >> var foo = require('foo'); >> spyOn(foo, "bar"); >> }); >> >> Just my 2 cents from a testing perspective. >> >> >> [1] - https://github.com/jhnns/rewire >> >> >> On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: >> >> > Create modules that are the smallest possible unit of code. Less code is >> > fast code. Faster to write. Faster to maintain. Faster to test. On the >> > extreme end characters in the Node community such as Substack advocate a >> > single function per module definition. >> > >> > module.exports = function() { >> > // my logic here >> > } >> > >> > This is kind of extreme and not always possible but a good practice >> > nonetheless. The idea is not new. Its a part of the UNIX philosophy: "do >> > one thing well" coined by Doug Mcilroy. [1] >> > >> > It can help you make code that looks like this [2] into this [3]. >> > >> > >> > >> > [1] http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html >> > [2] >> > >> > >> https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js >> > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js >> > >> > >
Re: [Node 101] Part 1: Small Modules
Maybe. Have a look at Substack's code and you'll see he has no trouble testing. The reason being he tests interfaces and outputs instead of implementations. That will be another Node 101! On Fri, Dec 13, 2013 at 10:24 AM, Gord Tanner wrote: > I also agree with this except for returning a function from module.exports. > > It is possible but makes mocking much much harder for testing. > > think of: > > > var foo = require('foo'); > > module.exports = { > awesome: function (a) { > foo(a+1); >} > }; > > It is kind of awkward to test this module's use of the foo module. It can > be done with rewire [1] but is a little awkward. > > If foo was designed where it exported an object literal with functions it > would be much easier to mock: > > var foo = require('foo'); > > module.exports = { > awesome: function (a) { > foo.bar(a+1); >} > }; > > it("calls foo.bar", function () { > var foo = require('foo'); > spyOn(foo, "bar"); > }); > > Just my 2 cents from a testing perspective. > > > [1] - https://github.com/jhnns/rewire > > > On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > > > Create modules that are the smallest possible unit of code. Less code is > > fast code. Faster to write. Faster to maintain. Faster to test. On the > > extreme end characters in the Node community such as Substack advocate a > > single function per module definition. > > > > module.exports = function() { > > // my logic here > > } > > > > This is kind of extreme and not always possible but a good practice > > nonetheless. The idea is not new. Its a part of the UNIX philosophy: "do > > one thing well" coined by Doug Mcilroy. [1] > > > > It can help you make code that looks like this [2] into this [3]. > > > > > > > > [1] http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html > > [2] > > > > > https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js > > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js > > >
Re: [Node 101] Part 1: Small Modules
I also agree with this except for returning a function from module.exports. It is possible but makes mocking much much harder for testing. think of: var foo = require('foo'); module.exports = { awesome: function (a) { foo(a+1); } }; It is kind of awkward to test this module's use of the foo module. It can be done with rewire [1] but is a little awkward. If foo was designed where it exported an object literal with functions it would be much easier to mock: var foo = require('foo'); module.exports = { awesome: function (a) { foo.bar(a+1); } }; it("calls foo.bar", function () { var foo = require('foo'); spyOn(foo, "bar"); }); Just my 2 cents from a testing perspective. [1] - https://github.com/jhnns/rewire On Thu, Dec 12, 2013 at 6:06 PM, Brian LeRoux wrote: > Create modules that are the smallest possible unit of code. Less code is > fast code. Faster to write. Faster to maintain. Faster to test. On the > extreme end characters in the Node community such as Substack advocate a > single function per module definition. > > module.exports = function() { > // my logic here > } > > This is kind of extreme and not always possible but a good practice > nonetheless. The idea is not new. Its a part of the UNIX philosophy: "do > one thing well" coined by Doug Mcilroy. [1] > > It can help you make code that looks like this [2] into this [3]. > > > > [1] http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html > [2] > > https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js > [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js >
[Node 101] Part 1: Small Modules
Create modules that are the smallest possible unit of code. Less code is fast code. Faster to write. Faster to maintain. Faster to test. On the extreme end characters in the Node community such as Substack advocate a single function per module definition. module.exports = function() { // my logic here } This is kind of extreme and not always possible but a good practice nonetheless. The idea is not new. Its a part of the UNIX philosophy: "do one thing well" coined by Doug Mcilroy. [1] It can help you make code that looks like this [2] into this [3]. [1] http://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html [2] https://github.com/apache/cordova-js/blob/c320378b484a172a02d3ee26634bcc584f43b939/Gruntfile.js [3] https://github.com/apache/cordova-js/blob/master/Gruntfile.js