{"id":14989725,"url":"https://github.com/shiling/testing-zero-to-hero","last_synced_at":"2025-04-12T00:31:50.942Z","repository":{"id":151322849,"uuid":"191278988","full_name":"shiling/testing-zero-to-hero","owner":"shiling","description":"Exercises for learning how to write Unit tests, API tests, End-to-end tests, and more...","archived":false,"fork":false,"pushed_at":"2023-07-26T05:19:42.000Z","size":1174,"stargazers_count":46,"open_issues_count":2,"forks_count":33,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-25T20:51:11.515Z","etag":null,"topics":["api-testing","chai","chai-http","end-to-end-testing","mocha","uilicious","unit-testing","webdriverio"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shiling.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-11T02:29:33.000Z","updated_at":"2024-11-19T04:18:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"4ef550d6-170e-4e37-9d13-302c0072ea74","html_url":"https://github.com/shiling/testing-zero-to-hero","commit_stats":{"total_commits":67,"total_committers":3,"mean_commits":"22.333333333333332","dds":"0.11940298507462688","last_synced_commit":"c7794b8132e5a6a906b9b7f828a45e08156eb3b7"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiling%2Ftesting-zero-to-hero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiling%2Ftesting-zero-to-hero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiling%2Ftesting-zero-to-hero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiling%2Ftesting-zero-to-hero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shiling","download_url":"https://codeload.github.com/shiling/testing-zero-to-hero/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248501352,"owners_count":21114661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-testing","chai","chai-http","end-to-end-testing","mocha","uilicious","unit-testing","webdriverio"],"created_at":"2024-09-24T14:18:49.910Z","updated_at":"2025-04-12T00:31:50.268Z","avatar_url":"https://github.com/shiling.png","language":"JavaScript","readme":"# Lab : Gotta catch them all!\n\n#  Introduction\n\nWelcome to the Pokedex!\n\nThis handy web application allows you to view information about all the pokemons currently known in the world.\n\nLet's add some tests to catch them all!\n\nIn this lab, we're going to write automate tests for this application:\n\n-   Chapter 1: Unit testing with [Mocha](https://mochajs.org) and [Chai](https://www.chaijs.com/)\n-   Chapter 2: API testing with [Chai-http](http://dareid.github.io/chakram/)\n-   Chapter 3: End-to-end acceptance testing with [UI-licious](https://snippet.uilicious.com)\n\n#  Setup\n\n##  Setting up the project\n\n👉 Fork this repository (https://github.com/shiling/testing-zero-to-hero) and clone it to your fork of the repository\n\n👉 Run `npm install` to to install the project dependencies.\n\n###  What is Mocha?\n\nWe are going to use Mocha as the framework for testing.\n\n[Mocha](https://mochajs.org) is a javascript testing framework, it helps you to manage the setup, execution, teardown, and reporting of your tests.\n\n#  Chapter 1 : Unit Testing\n\nLet's start with something simple - unit tests.\n\n##  What is unit testing?\n\nUnit tests are the smallest kinds of functional tests, and are designed to test a single method.\n\nA unit test should test if the method produces the correct output given certain inputs.\n\n###  💎 Execise 1.1: Hello Pikachu\n\nIn this exercise, we're going to try writing our first unit test for the `Pokemon` class in `models/Pokemon.js`. Let's test the `setName` method.\n\n👉 Open the file `1_pokemon.test.js` in the `/tests/1_unit_tests/` folder.\n\n👉 Import the Pokemon class:\n\n```javascript\nimport Pokemon from \"../../src/models/Pokemon.js\";\n```\n\n👉 Use `describe` to create a test suite for the `Pokemon` class and for the `setName` method, to group related tests:\n\n```javascript\ndescribe(\"Pokemon\", function() {\n    describe(\"#setName()\", function() {\n        // We'll write our test cases here\n    })\n})\n```\n\n👉 Use `it` to define the test `should set name when passed non-empty string`:\n\n```javascript\ndescribe(\"Pokemon\", function() {\n    describe(\"#setName()\", function() {\n        // Test Case 1\n        it(\"should set name when passed non-empty string\", function() {\n            // Steps to perform your test here:\n        })\n    })\n})\n```\n\n💡Tip: Just a like any other scientific test, a good test validates only one hypothesis at a time. A good software test should test **exactly one** requirement and validate the expected behavior(s) of the application.\n\n👉 Write the steps to perform `setName` method given a non-empty string:\n\n```javascript\nit(\"should set name when passed non-empty string\", function() {\n    // Steps to perform your test here:\n\n    // Create a pokemon, and set the name\n    let pokemon = new Pokemon()\n    pokemon.setName(\"Pikachu\")\n})\n```\n\nThe test is not complete without assertions to validate the output.\n\nNodeJS comes with an assertion library built-in - [\"assert\"](https://nodejs.org/api/assert.html).\n\n👉 Import the \"assert\" module\n\n```javascript\nimport assert from \"assert\"\n```\n\n👉 Now, let's add an assertion to make sure that the name of the pokemon is equal to the value we just set:\n\n```javascript\n// Test Case 1\nit(\"should set name when passed non-empty string\", function() {\n    // Steps to perform your test here:\n\n    // Create a pokemon, and set the name\n    let pokemon = new Pokemon()\n    pokemon.setName(\"Pikachu\")\n\n    // After setting the name, we must make sure that the name is \"Pikachu\"\n    assert.equal(pokemon.name, \"Pikachu\")\n})\n```\n\n👉 When you are done, run `npm run test:unit` in your console to run your tests.\n\n![Screenshot of test run](#)\n\n##  Using the Chai assertion library\n\nThe build-in \"assert\" library that comes with NodeJS provides you a basic assertion commands and doesn't provide very helpful error messages when assertions fail.\n\nMocha works with assertion libraries such as [Chai](https://www.chaijs.com/) which provides the syntax for writing the tests.\n\nChai is an assertion library on steroids, that lets you provides BDD-style `should` and `expect` syntax, as well as a more powerful `assert` library.\n\nChai also supports a lot of [plugins](https://www.chaijs.com/plugins/) to help you perform other useful assertions:\n\n-   [chai-http](https://www.chaijs.com/plugins/chai-http/) for testing http apis (we'll come to this later)\n-   [chai-json-schema](https://www.chaijs.com/plugins/chai-json-schema/) for testing json objects against a schema\n-   [chai-dom](https://www.chaijs.com/plugins/chai-dom/) for testing DOM elements\n-   [chai-url](https://www.chaijs.com/plugins/chai-dom/) for testing URLs\n-   [chai-file](https://www.chaijs.com/plugins/chai-files/) for testing files\n-   [chai-doge](https://www.chaijs.com/plugins/chai-doge/) wow, very doge-style language chains for Chai, much silly\n\n###  💎 Execise 1.2: Using `expect` syntax\n\nIn this exercise, let's try out Chai's `expect` syntax.\n\nImport Chai's `expect` library:\n\n```javascript\nimport {expect} from \"chai\";\n```\n\n`expect` allows you to write assertions like this:\n\n-   Type assertions : `expect(pokemon.name).to.be.a(\"string\")`\n-   Value assertions : `expect(pokemon.name).to.be.equal(\"Pikachu\")`\n-   Length assertions : `expect(pokemon.types).to.have.lengthOf(2)`\n-   and [more...](https://www.chaijs.com/api/bdd/)\n\n👉 Write the previous test using the `expect` syntax.\n\n##  Negative testing\n\nIt's important to also test negative scenarios, as user can make mistakes, and the application is expect to gracefully handle these accidents by showing appropriate errors to help users identify the problem and correct themselves.\n\n###  💎 Execise 1.3: Using `to.throw` to test exceptions\n\n👉 Using Chai's `expect(badFn).to.throw(error)`, test if an appropriate error is thrown when an empty string is passed to the `setName` method.\n\n#  Chapter 2 : API Testing\n\nNow, let's move one layer up and work on testing out APIs.\n\n##  Setup\n\n👉 Start the server:\n\n```bash\nnpm start\n```\n\nThe application will be loaded at [http://localhost:3000](http://localhost:3000)\n\n##  Writing API tests\n\nLet's test the `GET /api/pokedex/list` API which lists the pokemons in the database, and allows you to search for pokemons by attributes.\n\n###  💎 Execise 2.1: Writing an API test\n\nWe're going to use the [`chai-http`](https://www.chaijs.com/plugins/chai-http/) plugin which allows us to test http requests.\n\n👉 Open the file `2_pokedex_api.test.js` in the `/tests/2_api_tests/` folder.\n\n👉 Import and register the `chai-http` plugin\n\n```javascript\nimport chai from \"chai\"\nimport chaiHttp from \"chai-http\"\nchai.use(chaiHttp)\nimport { expect } from \"chai\"\n\n```\n\n👉 Write a test to retrieve all the pokemons using the `GET /api/pokedex/list` API, with the following assertions:\n\n```javascript\n// here's a template to help you get started\ndescribe(\"/api/pokedex\", function(){\n\n\tit(\"should return a list of pokemon as a json array using /list\", async function(){\n\n        // set a GET request to /list endpoint\n\t\tlet res = await chai.request(\"localhost:3000\").get(\"/api/pokedex/list\").send()\n\n        // you may print the response to the console to see its contents and debug\n\t\tconsole.log(\"response is: \", res)\n\n\t\t// 1: check status code is 200\n\t\t\n\n\t\t// 2: check that response content is a json array\n\t\t\n\n\t\t// 3: check that first item in the array is \"Bulbasaur\"\n\t\t\n\n\t})\n})\n```\n\n-   Assert that the response has a status of 200\n-   Assert that the response has a \"content-type\" header of \"application/json; charset=utf-8\"\n-   Assert that the response body is a json\n-   Assert that the response body is an array\n-   Assert that the response body is an array with 166 pokemons\n-   Assert that the name of the first pokemon is \"Bulbasaur\"\n    💡 Hint: You'll need [📖 this](https://www.chaijs.com/plugins/chai-http/)\n\n👉 Write a test to add a pokemon using the `POST /api/pokedex/list` API.\n\n#  Chapter 3 : End-to-end Acceptance Testing\n\n##  What is acceptance testing?\n\nA formal way of defining acceptance testing is to say that verifying that a software met business requirements.\n\nI think a better way and more **relatable** way to describe acceptance testing is that:\n\nAcceptance testing is verify that the application works for the **user**.\n\nTo perform acceptance testing, we need to simulate user stories, which should include:\n\n-   An **objective** that a user wants to achieve with the application,\n-   A series of actions that the user performs, which can be:\n    -   And a **happy** flow where a user performs valid actions\n        -   with assertions to validate that the application state and view is updated correctly\n    -   Or a **negative** flow where a user makes mistake (it's very human to do so!)\n        -   with assertions to validate that appropriate messages are shown to help the user recover from the error\n\n##  UI-licious\n\n###  💎 Execise 3.1: Testing with UI-licious\n\nWe can use GUI automation tools to automate acceptance testing.\n\nThe easiest way to test your web application is with [UI-licious Snippet](https://snippet.uilicious.com). ;)\n\n👉 Go to https://snippets.uilicious.com/ to access the free edition of UI-licious. It's like CodePen, but for testing.\n\n👉 Write a test to:\n\n-  Go to https://pokedex.uilicious.com\n-  Add a pokemon\n-  Go back to the pokedex\n-  Search for the pokemon that you've just added\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshiling%2Ftesting-zero-to-hero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshiling%2Ftesting-zero-to-hero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshiling%2Ftesting-zero-to-hero/lists"}