Ideas on a testing focussed code transform

Pranay Prakash at
Sat Dec 16 05:19:27 UTC 2017

Hmm, I suppose the stack traces drawback doesn't matter as long you're only
using this within the context of testing. The emphasis here is that the
actual application code that you run in production is what you wrote (the
imperative function calls), but when you 'require' the function into your
testing code, it gets transformed into this pure generator function that's
easier to test.

I don't see how the state/future of async functions affects this. In fact,
in my example, I use an async function to try and show that this transform
can even work for async functions (and will convert them to a synchronous
generator function rather easily)

On Fri, 15 Dec 2017 at 23:14 Isiah Meadows <isiahmeadows at> wrote:

> You're describing a variant of the interpreter pattern. I've used similar
> in task scheduling contexts, and the key drawback is you no longer have
> useful stack traces.
> I haven't done any formal research on the approach, though. I will caution
> you that async functions are already widely used enough (particularly in
> Node) they're unlikely to go anywhere beyond something drastic.
> On Sat, Dec 16, 2017, 00:07 Pranay Prakash < at> wrote:
>> Hey all,
>> I was just reading the docs for `redux-saga` where I encountered a nice
>> design pattern for a saga which is (correct me if I'm wrong) a
>> regular javascript generator function that yields the intent to call a
>> function (instead of actually calling a function) until it goes through all
>> the steps. If that doesn't make sense, consider this simple function:
>> ```
>> async function findFriends() {
>>   const myId = getMyID();
>>   const myUser = await fetchUser(myId);
>>   return myUser.friends;
>> }
>> ```
>> instead of actually making the function calls needed, we can instead have
>> a function that does something like this:
>> ```
>> function* findFriends() {
>>   const myId = yield { fn: getMyID };
>>   const myUser = yield { fn: fetchUser, args: [myId] };
>>   return myUser.friends;
>> }
>> ```
>> This is a pure generator function that doesn't actually do anything, but
>> has all the necessary information to recreate the original function[1] (or
>> have a library "trampoline" through the function and make all the necessary
>> calls for you)
>> A HUGE plus of the second version of the function is that it's *easily*
>> testable (unlike the first one). Pure functions are easier to test. Testing
>> this is simply a matter of calling `.next()`, getting the "intent", making
>> sure the right intent was yielded (good enough for unit testing) and
>> calling `.next()` again with the "mock" value, you want to return and
>> continue to test.
>> An observation to make here is that you can transform the original
>> version of this code (easy, normal code to write) to the latter (easy code
>> to test). So, what about having some sort of babel transform perhaps that
>> can convert the first to the second but only in the context of unit tests.
>> You write code the normal way as you would for your application and don't
>> worry about test suite implementation details (mocking/dependency
>> injection/etc.), and when you want to test, simply import your function
>> (which gets converted to a generator) and step through it to test different
>> scenarios.
>> I personally think this is a super clean way to do testing since
>> the tests never interfere with how you actually write the code AND you
>> don't have to explicitly mock.
>> Does anyone have thoughts on this / prior research (or knows about an
>> existing implementation of this)?
>> Cheers,
>> Pranay
> _______________________________________________
>> es-discuss mailing list
>> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list