mcibique / vue-testing-examples

Advanced testing with vuejs. When you need to go beyond Getting started section and see some real world example with everything that proper tests should have.
MIT License
339 stars 36 forks source link

where is your blog? #1

Open namespace-io opened 6 years ago

namespace-io commented 6 years ago

Hi, i'm learning how to test a vue project recently so i star this. since i'm a rookie in js and i'm looking forward to your explain about this project such as what you use in this project and why use them and how to use them.i want to what's principle in it and how to design them. so i write this because you don't show you email. if you don't mind, I want look at your blog and learn :) . else i'm going to read your commits one by one :( thank you very very very ... much!

mcibique commented 6 years ago

Hi, thanks for checking out the repo. There is no blog, I'm writing everything into the README file. I don't have much time to do that, but I have already managed to cover some decisions. I would like to focus mainly on testing techniques because those are not very well covered in any official documentation. If there is anything in particular not clear to you, then let me know. Any feedback is welcome.

namespace-io commented 6 years ago
Thanks for your reply.
since i have no idea about 'di' & 'ts', so i searched for a while.
here is my understanding, 
  'di' is a kind of design principle
  for example, 
    if in A.actionA() we call B.actionB() [V1] 
    we can user interfaceActionB, then B implements interfaceActionB, 
    A only call interfaceActionB rather than directly call B.actionB
    in this way, we separate B from A, A depends on interfaceActionB,
     and B depends(implements) interfaceActionB [V2]
    in V1, we must and need to care how to create InstanceB(because we use B to invoke actionB)
    in V2, we don't care, we can deliver details(eg.how to create B) to FactoryFunction.
    But when we meet multi-dependences or something must be created by orders. 
    for example, in { A(B,C), B(C), C() }, we must frist create C, then B, finally A
      if numbers of classes up to 1000 and multi-dependences must be much more complex,
         this will be a disaster for our code and makes the code much harder to maintain 
      so we need a frame(Third Part Container) to help us and manage the classes
        with Container, we don't care detailes(how to create them or orders), 
        we just make declare(Register)
        @Register(key_A, [key_list])
        class A{} 
        means when we use InstanceA ,according to [key_list] that already have been registered 
        in Container (as (key_B, B) for example, right ?),we know which [classes] are needed 
        and get [Instances] from Container finally we get InstanceA
        we don't need to care about the order, the order are solved by Container.
        In other words, the Container is similiar to FactoryFunction(both create Instance), 
        but more Advanced because Container keep us away from orders(i.e. code logic),
        we can focus more on project logic
        now,we can write 
        @Register (key_A, [key_B])
        class A{             |
          constructor(B){<---| automatically B = Container.get(key_B), right?
            this.B = B
          }
          actionA(){ this.B->actionB}
        } [V3]
        In V1, we create InstanceB(e.g. new B) in class A
        In V2, we need FactoryFunction and we need orders of creation
        In V3, we don't create InstanceB, all creation problems are solved by Third Part Container
this is my rough understanding, if i get something wrong, please help to point out these mistakes,
because i have on idea about 'ts' & 'InversifyJS', so it need some time(maybe 1-3days) to understand 
how to write them such as bind(key).to(class) means @Register(key, class)?( at code level, maybe i
will ask you later(ฅ´ω`ฅ) )
        thanks for your generosity. Look forward to your favourable reply.
mcibique commented 6 years ago

Your understanding is right. :1st_place_medal:

I have expanded the section with Register decorator: https://github.com/mcibique/vue-testing-examples#register-decorator for better understanding what's going on under the hood.

I have also added few examples of DI in action: https://github.com/mcibique/vue-testing-examples#why-dependency-injection, to show that DI is not only about maintaining large dependency trees and mocking in unit tests, but it can help in other situations too.

namespace-io commented 6 years ago

i find Testing Vuex in components(Official documentation), in this example, they mock store in Smart components that's not accordance with yours your table, i get confused and Q1: i wonder which is right or there is no standard design about this

you said We should mock out only a necessary minimum from the component, emmm..
Q2: what's the necessary minimum from the component? i have very little knowledge of testing theory.Your links are very useful,they give me a much grander view. there are principles(tell us what we can do and what we can't do) Have we had "best practices"? if it's, please tell me or maybe we can get inspiration from React

mcibique commented 6 years ago

Q1: I started with the exact same tutorial as you mentioned, but this just doesn't work with any project I have been working on. The idea is nice, the solution looks good, but it doesn't scale very well for larger applications. It adds lots of additional code for each component tests and in many cases, the mock does exactly the same thing as logic in the store. A better solution is to reuse existing store as it is. I have added a new section (https://github.com/mcibique/vue-testing-examples#mocking-store-vuex) to cover this topic little more and how to reuse the store.

Q2: I think I'm going to rephrase it. It should be saying "You should mock as less as it gets". If you keep original application logic intact during all your tests, then more confidence you get about your component working properly.

Let's say you have a smart component which uses a store, router, 3rd party UI library (material or bootstrap), REST API, native browser APIs (canvas, localStorage) and also communicates with workers. If you decide to use only unit tests, all these parts must go away and be mocked. If you decide to go with integration tests because they suit better for smart components, then these parts should stay. It's not always possible, e.g. API calls cannot be executed because there's no server available. Native browser APIs can be problematic. If you run your tests with Karma and Chrome/Firefox, you have canvas available. But if you run your tests with mocha and jsdom, you don't have canvas, you have to mock it. Same can happen with workers and localStorage. You might have a service which needs to communicate with a browser extension, that's also not possible. On the other hand, store, router and 3rd party libraries usually don't require any special APIs thus they can stay without mocking.

There is one amazing library for testing React which you can check out: https://github.com/kentcdodds/react-testing-library, written by Kent C Dodds who does workshops on testing, talks on egghead.io about components. The library was introduced just recently, has also couple links to guidelines and what I like they also realize that integration tests are a thing, they don't even have shallow rendering.

namespace-io commented 6 years ago

i think it make some sense,we trust 3rd-UI and Vue. but we can't make sure store or router is correct. according to you analysis, we must make sure the store is correct first then do other tests. otherwise how we can know whether store or Login.vue is wrong when Login.vue.spec.js throw error it means we must first make sure this global things(e.g. 3rd-UI,localVue,store,router) are correct then we do tests ?