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

Simulation mode, SVP #1095

Closed
suntong opened this Issue Feb 10, 2018 · 15 comments

Comments

Projects
None yet
2 participants
@suntong
Contributor

suntong commented Feb 10, 2018

Would providing a Simulation mode a good idea, SVP?

Since web weichat is so picky and touchy (ref #603), playing it safe would be greatly desired and appreciated.

Thanks

@zixia

This comment has been minimized.

Member

zixia commented Feb 11, 2018

Develop inside a simulator looks a good idea for me because that will not only prevent to be blocked by Tencent by mistake but also can test our code more efficiently.

Any future suggestion/designs/discussions are welcome!

BTW: what's SVP? Simulation V... P... ?

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 11, 2018

Ha, first of all, I thought you might ask what SVP is, so I provided a link for you. Click it and you'll understand. :-)

Now as for the simulator, I think the best approach is to

提供一个基于HTTP协议的API接口 ,简洁丰富,方便和其他编程语言集成

just like how the Mojo-Weixin does, however, such API is not for other apps to interact with Weixin, but for a driving app to send requests so as to simulate what wechaty would have received from Weixin. Furthermore, such driving app is best to be a CLI command, i.e., changing the command-line parameters would change different test cases.

I'm afraid that's all that I can say for the moment, as I don't have internal insights into the wechaty implementation, nor the Weixin communication protocol. The good things are,

  • While considering the API, you can think about the APIs for the above two different purposes (event driven & event driving API) and plan for them both at the same time.
  • For the time being, you can only implement the event driving API first.
  • If node is not the best tool to write command-line tools, we can use other language as well. That's the true beauty of providing such HTTP-Json based API.

Get the event driving API drafted first, and we can go from there. I am not much help for this, but I'm sure other contributors will chip in. Moreover, I can help with building the event driving command-line tool if nobody volunteers. But that'd be in Go though, the language that I love and prefer. Or, hmm... actually, with the best designed API (of HTTP & Json), the best driving command-line tool should be curl. E.g., check out how I can post to GitHub Gists from command-line with curl for e.g.

Glad you like the idea. cheers.

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 11, 2018

SVP means, S'il vous plaît, French for "Please", :-)

@zixia

This comment has been minimized.

Member

zixia commented Feb 12, 2018

I have an idea that we can build a WechatyMock module, for use case testing.

For example, when we had wroten a Wechaty bot, we want to test it before actually use a REAL Wechat account with Tencent server, we need this to make our code testable.

So we could consider introducing a new module named WechatyMock like this:

const wechatyMock = new WechatyMock()

let loginedUser

wechatyMock
.on('login', user => loginedUser = loginedUser)
.on('message', msg => {
  if (msg.content() === 'hello') {
    msg.from().say('world')
  }
})
.start()

// unit test case 1: login
const mockUser = new wechatyMock.Contact('huan')
wechatyMock.mockLogin(mockUser)
assert(loginedUser === mockUser)

// unit test case 2: message event
const mockMsg = new wechatyMock.Message(mockUser, mockUser, 'hello')
sinon.stub(mockMsg, 'from')
        .onFirstCall().returns(mockUser)
saySpy = sinon.spy(mockUser.prototype, 'say')

wechatyMock.mockMessage(mockMsg)
assert(saySpy.firstCall.args[0], 'world')

I hope the above code snip would reflect what your suggestion, please let me know what you think.

Thanks!

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 12, 2018

Yes, that's a good way to unit test the module code itself. However, let's shift our view from the module author prospective to the module end-users' for a moment, and this is what I have envisioned:

const { Wechaty } = require('wechaty') // import Wechaty from 'wechaty'

Wechaty.instance() // Singleton
.simulate(true)
.on('scan', (url, code) => console.log(`Scan QR Code to login`))
.on('login',       user => console.log(`User ${user} logined`))
.on('message',  message => console.log(`Message: ${message}`))
.init()

I.e.,

  • the module end-users don't need to change any of their code to use the simulation mode, except for turning it on by, say, .simulate(true). I.e., the cost is minimum.
  • they can turn it off any time by toggle .simulate(true) to false, or comment out the line. I.e., switching is easy.

Now how to simulate?

We open another terminate, and send request to the wechaty in simulation mode by the designed API, say of HTTP & Json, and these are what I have in mind:

{
  "MsgType": "TEXT",
  "Content": "ding",
  "From": "From is optional"
}
{
  "MsgType": "IMAGE",
  "Case": 0
}
  • Instead of "IMAGE", it can also be VOICE, VIDEO, MICROVIDEO, etc (and how about the shared article BTW?)
  • Case === 0 is optional, Case == 1, 2, ... is for other ready defined unit test samples

Such requests will be relayed by the wechaty in simulation mode to user's code.

So the unit testing on the end-users code is to compare the simulation output with the standard, e.g.,

Scan QR Code to login
User SimulatedUser logined
Message: ding

And unit testing on wechaty module code itself will be the same too.

How is that?

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 12, 2018

By "compare the (simulation) output with the standard", this is the mechanism I used, which is quite versatile and easy to adapt.

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 12, 2018

Or,

Maybe to tweak on the import, e.g., letting the user toggling between the following two line will toggle the simulation mode:

// const wechaty = new Wechaty()
const wechaty = new WechatyMock()

I don't know Javascript so I'm just suggesting. I.e., anything should be OK, as long as the cost is minimum, and switching is easy.

@zixia zixia added the enhancement label Feb 14, 2018

@zixia

This comment has been minimized.

Member

zixia commented Feb 14, 2018

Thanks for sharing your thoughts, I agree with you that we should let user toggling easily.

We should consider introducing a WechatyMock with both program & restful API support because it will make Unit Test & Interactive Test possible and easy. Also, a REPL mode will be nice if possible.

The following syntax will be most effective when we need to toggle:

import { WechatyMock as Wechaty } from 'wechaty'

Or, with future thoughts, the WechatyMock might just be a Puppet, which will let us interact with the programming API / restful API / REPL.

Wechaty.instance({
  puppet: PuppetRestful,  // PuppetREPL, PuppetAPI
})

See Also

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 14, 2018

import { WechatyMock as Wechaty } from 'wechaty'

Yeah, perfect. Let's go with that, regardless what the WechatyMock might just be internally.

And sure, a REPL mode will be nice, after we have the Unit-Test / restful-API capability.

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 19, 2018

take your time @zixia, as I've come up with my own simulation for my own simple test case. Ref

https://github.com/suntong/nodecl/blob/master/sbaa/test_msg.js
https://github.com/suntong/nodecl/blob/master/sbaa/test_msg.sh

@zixia

This comment has been minimized.

Member

zixia commented Feb 19, 2018

@suntong Nice start, I'm happy to see that.

Go ahead and please let me know if you have future updates for that!

@suntong

This comment has been minimized.

Contributor

suntong commented Feb 19, 2018

Sure. thx.

Had I been writing my code in TypeScript, it'd be impossible to write such simulation in such simple way. :)

@zixia

This comment has been minimized.

Member

zixia commented Apr 30, 2018

Merge to #1177

@zixia zixia closed this Apr 30, 2018

@zixia zixia added the duplicate label Apr 30, 2018

@suntong

This comment has been minimized.

Contributor

suntong commented Apr 30, 2018

That's excellent @zixia!

I took a look trying to find a sample code using the new PuppetMock, but didn't find one.
Hope a demo code will be available soon. thx!

@zixia

This comment has been minimized.

Member

zixia commented Apr 30, 2018

It's in heavy developing now.

If you want to play with those codes(also play with lots of bugs), you can:

  1. find the new PuppetMock source code at https://github.com/Chatie/wechaty/tree/39b38baafbb3cced482218215ee63dff40be9ddf/src/puppet-mock
  2. test the PuppetMock by running WECHATY_PUPPET=mock npm run demo with the latest master code. (which currently is v0.15.26)

Please feel free to leave comments to discuss more, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment