Search code examples
javascripttestingvue.jstddkarma-mocha

Learning to test Vue.js projects: product display list


I have a small Vue.js application which fetches and displays a list of products. The application must allow to sort products by size, by price range, alphabetically, etc - all forwards and backwards.

There's unit tests, integration tests, E2E tests etc.

For this particular application, I imagine that:

  • Unit Tests are responsible for testing Component methods

  • Integration tests: Responsible for the output of a certain action/function:

    • Are there in fact products displayed?
    • Is the price range between 0% and 100% returning any products products?
  • E2E tests - not exactly sure.

In this particular simplistic example, which tests should be there to cover the absolute minimum?

Any thoughts appreciated!


Solution

  • First, your definitions are not exactly correct. I strongly recommand that you take a look at Vitali Zaidman's Overview of JavaScript Testing in 2018.

    You will find the difference between the test types :

    • Unit Tests- Testing of individual functions or classes by supplying input and making sure the output is as expected.

    • Integration Tests- Testing processes or components to behave as expected, including the side effects.

    • UI Tests- (A.K.A Functional Tests) Testing scenarios on the product itself, by controlling the browser or the website, regardless of the internal structure to ensure expected behavior.

    You will also learn about all the different test tools types, the available frameworks, and basically everything you need to get started and test your components.

    Regarding which tests should be there to cover the absolute minimum, it's subjective. I personally like to tests every computed properties, watchers, lifecycle hooks and methods (everything that has logic in it), but it can be a bit much in your case, it's your call !


    Edit :

    You asked my how to write GOOD tests and, again, it's very subjective.

    You can find a new way of doing things for every blog article.

    What's most important is that every unit test must assert only one behavior. The tests structure is also very important

    Here's an example, if I had to test a component that display products like in your case :

    Note : Here I am using Jest and Vue Test Utils but you can use the framework you like, I am just showing you my way of doing it on very simple and straightforward parts.

    My component has a computed property displayedProducts, that takes the products data and sort it by name in ascending or descending order, based on a order data.

    // Products.spec.js
    
    // Importing vue-test-utils methods (see the API doc : https://vue-test-utils.vuejs.org/en/api/)
    import { mount } from '@vue/test-utils';
    // Importing the tested component
    import Products from '@/[...]/Product';
    
    describe('Products.vue', () => {
      // vue-test-utils' wrapper and Vue instance, used in every tests
      let wrapper;
      let vm;
      const productsMock = [{
        name: 'First product',
      }, {
        name: 'Second product',
      }];
    
      // Before each test, we mount a new instance
      beforeEach(() => {
        // Mounting and inject the products (see the complete documentation here : https://vue-test-utils.vuejs.org/en/api/mount.html)
        wrapper = mount(Products, {
          products: productsMock,
        });
        vm = wrapper.vm; 
      });
    
      // Nested 'describe' to make your tests more verbose
      describe('products', () => {
        // Basic test, display the list ordered by names in ascending order
        it('should display the products', () => {
          expect(vm.displayedProducts).toBe(productsMock);
        });
    
        // Test that the list is reversed when 
        it('should reverse the products list when ordering in descending order', () => {
          vm.order = 'desc';
          expect(vm.displayedProducts).toBe(productsMock.reverse());
        });
    
        // [...] test that the order's default value is 'asc'
        // [...] test that the list is sorted by the right value, etc...
      });
    });
    

    Note that the tests are readable, going from the first describe to the it (example : Products.vue => products => should display the products).

    You really should read the entire Vue Test Utils documentation, to be familiar with every aspect of Vue.js' tests.