# Guide to writing unit tests Unit tests are good because they allow us to: - Ensure that something is working properly now. - Ensure that something will continue to work properly in the future. ## Creating a unit test ### Creating the file To start writing a unit test for SS13, locate the unit test folder. This folder is stored at `code/modules/unit_tests`. Inside of that folder, create a new file with an appropriate name. If you are using VS code, your file will automatically be included in the beestation.dme file. **Remove your unit test from the beestation.dme file and add it to the _unit_tests.dm file instead** ![](https://hackmd.io/_uploads/Hy7hoixea.png) These should be in alphabetical order. ### Setting up the datum To create a unit test, you need to create a subtype of `/datum/unit_test` and implement the `Run()` method. ``` /datum/unit_test/example/Run() Fail("This test is failing") ``` #### Tests involving creating physical objects You may need to create objects in the world in order to test certain things, such as objects linking to other objects on mapload. You can use the `run_loc_floor_bottom_left` provided by `/datum/unit_test` in order to find the turf at the bottom left of the allocated area. You can access the x, y and z coordinates to find adjacent locations. `run_loc_floor_top_right` does what you would expect. ``` /datum/unit_test/test_mob_hitting/Run() var/mob/living/carbon/human/test_human = new(run_loc_floor_bottom_left) var/mob/living/carbon/human/test_target = new(step(run_loc_floor_bottom_left, EAST)) // Click on the test target. // If we were actually testing something we should enforce that // the mob is on the correct a_intent first if we were testing punching. test_human.Click(test_target) ``` ### Performing some assertions Assertions ensure that certain values are what we would expect them to be. If a test runs to completion without failing, then it will succeed. You do not explicitly need to mark a test as succeeded as it is assumed to be successful if it hasn't failed. #### Testing that a value is equal to another value If you want to ensure that something is equal to what you would expect, you can use the `TEST_ASSERT_EQUAL` define. ``` TEST_ASSERT_EQUAL(2 + 2, 4, "2+2 should be equal to 4.") ``` On the left you put the actual value and on the right you put the expected value. This will instantly fail with the message provided, so if you have lots of things to test you may want to use another approach. #### Manually triggering a failure You can call the `Fail` proc in order to instantly trigger a test failure. You can also use this to collect many errors and then display them all at once. ``` if (2 + 2 != 4) Fail("Expected 2 + 2 to be equal to 4, but it was not.") ``` Or: ``` var/list/failures = list() if (2 + 2 != 4) failures += "Expected 2 + 2 to be equal to 4, but it was not." if (2 + 3 != 5) failures += "Expected 2 + 3 to be equal to 5, but it was not." if (length(failures)) Fail(jointext(failures, ", ")) ``` ### Testing Tips and Top Practices - Try to assume as little as possible. If you are testing a human punching another human, then set the attacker's a_intent to harm intent before performing the click, even if harm intent is the default mode for a mob. - Try to make your tests test a single specific area. - Make your error messages useful. If you are testing a lot of things that can fail together, rather than using Fail() which only gives the name of the first thing that fails, you can create a list of errors and then print the entire list at the end. See `crafting_tests.dm` for an example. ### Running unit tests You can run unit tests if you have the tgstation test explorer plugin for VS code. This will give you a tab that looks like this. ![](https://hackmd.io/_uploads/H1qMQnglT.png) You can press the play button next to any test in order to run it, it will compile the repository and then run the test. This may take some time but it is usually faster than launching the game fully and waiting for the round to be ready to start. ## FAQ **What needs unit tests?** Anything that can be easily tested. The best way to find something that should have a unit test is to browse through the repository issues and find things that would be easy to make a test for. **What should I be careful of when making unit tests?** Anything that requires a specific configuration setting or database setting cannot be tested as this relies on external files that won't be the same on the repository and live server. If you are going to use a configuration setting, you should explicitly set it in the unit test to a value that you control. **Is there a list of things that would be easy to unit test?** Yes! See https://github.com/BeeStation/BeeStation-Hornet/projects/2#column-19642571 for a list of things that are easy to unit test. These are a list of things that were in the issues tab and would be easy to write unit tests for. **Can I get any additional help?** Yes, feel free to ask any questions on our discord and someone will be happy to help out! discord.gg/ss13