Search Unity

Question Backup and file upload test

Discussion in 'Testing & Automation' started by Nharny, Nov 3, 2022.

  1. Nharny

    Nharny

    Joined:
    Apr 25, 2020
    Posts:
    2
    Hello,

    I'm doing my first steps with unit tests under unity.

    I would like to test my backup system (creation and loading of Json files).

    But the problem is that if I want to test for example the backup, the first thing I will do is to check if my file has been created. For that no problem.

    But the second thing I want to check is if my file contains the right information.
    But how can I do this without using my file upload method?

    Because I'm not in the case of a unit test anymore if my test depends on another method that I've also developed.

    If I want to test the loading it is already a simpler case:

    I can have a file that I load and check if the data retrieved is the right one.

    But if I create a file via the code I will have to use the backup method and I find myself in the same case as for the backup tests.

    Thanks in advance for your answers.
     
  2. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,657
    I think the first thing to consider is why it's a problem to be 'not in the case of a unit test anymore'. The general principle your test would be violating is "a test should only have one reason to fail," but it's important to understand why that principle is helpful, and whether the help it brings you actually outweighs the costs of sticking to it in this case. Remember that the goal of writing tests is to help you find/prevent bugs and improve maintainability of the codebase - having 'textbook-quality tests' is not the goal (unless you're writing a textbook, I guess).

    The particular reason I say this is because in your case, it sounds like the right way to stick to the 'only one reason to fail' would be to write code in your test which knows how to load your backup and check certain things about it.

    It's possible that you can do this without replicating the entire file-load routine. Maybe you can just load it with System.IO and then check for the presence of particular strings, or use something like Newtonsoft.Json.Schema to check that the data you've saved conforms to a particular structure.

    But if the checking you want to do is extensive, then you might find you've basically re-implemented the whole file-loading routine inside your test, and at that point I'd definitely think seriously about whether it brings sufficient value. There are situations where it can work very well, like having a 'reference implementation' (which is always 100% correct, but not super fast) for the tests while the production code is using a more optimized implementation. But in other situations all you've done is double your maintenance burden, making it so that whenever you want to add a new field to your backups, you have to add it in two places instead of one, and you have twice as many places that bugs could exist in, etc.
     
  3. Nharny

    Nharny

    Joined:
    Apr 25, 2020
    Posts:
    2
    Thank you very much for the answer.
    For the moment I'm having a hard time getting away from the theory, I'm just starting to really practice unit testing.

    Newtonsoft has helped me a lot. I had a little bit of trouble getting it to work but that's because I don't know the assembly well.

    At the code level it gives me this for the moment:


    Code (CSharp):
    1. public class SaveDataTestEdit
    2. {
    3.     private string expectedJsonFilePath = Application.persistentDataPath + "/expected.json";
    4.     private string receivedPath = Application.persistentDataPath + "/savefile.json";
    5.  
    6.     [OneTimeSetUp]
    7.     public void Setup()
    8.     {
    9.         int NumberOfHighScoreGenerated = 2;
    10.         ScoreData scoreExpected = new ScoreData();
    11.        
    12.  
    13.         for (int i = 0; i<NumberOfHighScoreGenerated; i++)
    14.         {
    15.             HighScore highScoreExpected = new HighScore();
    16.             highScoreExpected.PlayerName = "PlayerNameTest" + i;
    17.             highScoreExpected.Score = i;
    18.             scoreExpected.highScores.Add(highScoreExpected);
    19.         }
    20.  
    21.         string jsonExpected = JsonUtility.ToJson(scoreExpected);
    22.         File.WriteAllText(expectedJsonFilePath, jsonExpected);
    23.     }
    24.  
    25.     [OneTimeTearDown]
    26.     public void OneTimeTearDown()
    27.     {
    28.         File.Delete(expectedJsonFilePath);
    29.     }
    30.    
    31.     [Test]
    32.     public void SaveHighScoreIsOkTest()
    33.     {
    34.         SaveData saveData = new();
    35.         saveData.SaveHighScores();
    36.         JToken received = File.ReadAllText(receivedPath);
    37.         JToken expected = File.ReadAllText(expectedJsonFilePath);
    38.         Assert.IsTrue(JToken.DeepEquals(received, expected));      
    39.     }
    40. }
    The SaveHighScores method is not finalized yet but I'm trying to test it as I go along. The goal is to get to the end to do TDD.

    I think that testing that the backup works was a first step.