Search Unity

Feedback for LogAssert class

Discussion in 'Testing & Automation' started by liortal, May 8, 2018.

  1. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Howdy,

    Today was my first attempt of using the LogAssert class. I had spend a looong time to figure out why my test isn't working as i expect it to. Here is feedback about this class after trying (and failing) to use it properly today:

    * First off, i tried looking for "logassert" on the forums and feedback site. Found 0 results.. this class doesn't really look like a popular one at the moment (which is great, since it can be easier to modify it without pissing off too many people!)
    • All tests have this "hard-wired" behaviour that will basically fail them in case an error is logged to the console. It could've been a lot nicer (and cleaner) to be able to toggle this behaviour directly from the [Test] or [UnityTest] attributes. Something like this:
    Code (CSharp):
    1. [UnityTest(IgnoreLogErrors = true)]
    2. public IEnumerator MyTest()
    3. {
    4.     // ...
    5. }
    This behaviour is related to the test itself, why should another class be responsible for turning this behaviour off? also, this way allows for more freedom (turning off for a specific test).
    • In case i'm ignoring exceptions / error logs (so they don't fail my test), any Asserts i make will not cause the test to fail as well:
    Code (CSharp):
    1. [UnityTest]
    2. public IEnumerator Test()
    3. {
    4.     yield return null;
    5.  
    6.     LogAssert.ignoreFailingMessages = true; // with this, asserts below will not fail the test
    7.  
    8.     Assert.That(0 == 2, "0 isn't equal to 2");
    9.     Assert.AreEqual(0, 2, "0 isn't equal to 2");
    10. }
    This test passes (only tested for PlayMode test, but i suppose it'll be the same for editor tests as well). Not sure this is the desired behaviour... how can i fail the test now basically ?
    • The Expect method (!!) is my biggest rant here. since it's a static method, i somehow assumed that setting it to expect a particular log type + msg will mean that *any* log messages like that will not fail the test. In reality, it only matches a single log message and then moves on.
    For example, in my test i had set something like this:
    LogAssert.Expect(LogType.Error, new Regex("duplicate key for.+"));

    During my test, any number of messages from that form might be logged, and i don't want them to fail my test. With the current API, this only matches a single log message, but any subsequent error logs fail the build.

    I realize this might be similar to other test frameworks, but it was still confusing to use and i had to spend a lot of time figuring out why it didn't work.

    This can be solved in any number of ways, for example:

    - LogAssert.ExpectOnce / LogAsset.ExpectAny
    - LogAssert.Expect(string, int) --> expect a log message for the given number of times (-1 for any number?)
    - Updating the documentation to stress out this fact. Currently this is the description (not sure if it's clear enough):
    • Another issue - the Expect method will not fail the test in case a log that matches the expectation is seen, but will fail in case it's missing. basically, there's no API to say "don't fail my test in case this error message is shown". Should be added somehow to make it easier to ignore certain error messages.
    Please consider this feedback when making changes to LogAssert or to the unit test framework in Unity :)
     
    Last edited: Jan 6, 2019
  2. ElvisAlistar

    ElvisAlistar

    Unity Technologies

    Joined:
    Oct 2, 2013
    Posts:
    226
    Thanks for the feedback. All very valid points and we should implement as much of it as possible.
     
    liortal likes this.
  3. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    The test framework and other supporting libraries should probably be open sourced, so i can fix it for myself locally (as well as push those changes over to you, in case you're interested).
     
  4. ElvisAlistar

    ElvisAlistar

    Unity Technologies

    Joined:
    Oct 2, 2013
    Posts:
    226
    It will become a Unity package soon, so you will be able to change it locally.
     
  5. mpartel

    mpartel

    Joined:
    Mar 9, 2013
    Posts:
    2
    I was surprised to find that that multiple
    Expect
    calls will expect the log messages to appear in that order. This ought to be documented and ideally made optional.
     
    liortal likes this.
  6. mpartel

    mpartel

    Joined:
    Mar 9, 2013
    Posts:
    2
    And there appears to be something weird with calling
    NoUnexpectedReceived
    multiple times. This is the minimal test case I came up with:

    Code (CSharp):
    1.  
    2. LogAssert.Expect(LogType.Log, "Hi");
    3. Debug.Log("Hi");
    4. LogAssert.NoUnexpectedReceived();
    5.  
    6. LogAssert.Expect(LogType.Log, "Hi");
    7. Debug.Log("Hi");
    8. LogAssert.NoUnexpectedReceived();
    It complains about the second log message not being expected.
    Remove either of the calls or change either of the log messages and it stops failing.
     
  7. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Any interesting updates about the test runner or test framework in general? @ElvisAlistar
    I am actually using it more often nowadays and i have a few other things that could be useful.

    Just open source it and i will do the rest :)
     
  8. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    how are you using ignoreFailingMessages? are you setting it up in the beginning of the test?
    You're catching the exception, but it's still logged to the console?
     
  9. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    any updates you're able to share with us?
     
  10. Warnecke

    Warnecke

    Unity Technologies

    Joined:
    Nov 28, 2017
    Posts:
    92
    We are still working on it actively, but I cannot give any specific timeframe.
     
  11. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    It's been almost a year. What's the delay? Should we continue using UnityTestFramework (since it's apparently not getting updates) and do our own integrations of NUnit instead?

    Core features are still missing - can't mock MonoBehaviour even using the NUnit features specifcially created for doing so - but when we build this stuff itself (without any of Unity's code) it Just works. I found a couple more core bugs in Unity 2018's implementation of the Test framework - stuff that makes it almost completely useless (Unity outputs the wrong error messages and actively corrupts the code its running!). Lost a few hours discovering that. What gives?
     
  12. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    i really wish they would open source the whole thing. i am really into unit testing and would love to donate any fixes or improvements to this framework for the sake of all Unity devs!
     
    dan_ginovker likes this.
  13. Warnecke

    Warnecke

    Unity Technologies

    Joined:
    Nov 28, 2017
    Posts:
    92
    Hey

    Internally in Unity we are using the Unity Test Framework heavily. Currently we run 4 million test runs daily on that framework. It is a test framework that we are betting on internally and thus you can be sure that we will keep supporting it.

    The iteration time for us to fix issues and apply feedback to the framework is currently not good enough and that is our main motivation to move the framework into a package. It is however, due to our heavy usage of the test framework that it is taking a long time to make the switch to a package. We plan to ship it as a package in 2019.2.
     
    liortal likes this.
  14. jonbro5556

    jonbro5556

    Joined:
    Jan 1, 2013
    Posts:
    24
    I just want to add a request for having more access to this. I know this isn't the most active part of the forum - thought I would throw another vote here for package + better access.

    The feature that I am really missing is being able to run tests on standalone platform builds without having the editor kick off the tests. Also, it would be great to not need a network connection for capturing the output.

    The pipe line I am working in means that I can't have dedicated editors per each device running the test builds, and I can't be guaranteed network access between my devices and the network either. In addition not all platforms yet support "Run all in Player" - it would be nice to short cut this.
     
  15. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    In regard to the following line causing tests to pass even when asserts fail:
    Code (CSharp):
    1. LogAssert.ignoreFailingMessages = true;
    I just spent about 4 hours tracking this issue down and came here to post about it. Sad to hear it has been unresolved in more than a year. We have unit tests that cover 3rd party plugins, some of which are logging errors that don't concern us. Without that line of code, our tests fail due to these errors that we don't care about. With it, our tests never fail even if they should.
     
  16. Stormy102

    Stormy102

    Joined:
    Jan 17, 2014
    Posts:
    495
    We do use LogAssert but the only use we have for it is Unit Testing our in-game dev console. Therefore we know exactly what LogError input we're going to pipe through it. It would be helpful to just blanket ignore X number of tests or turn it off altogether. The code in LogAssert.Expect works exactly as (pardon the pun) expected, so porting that to work with LogAssert.ignoreFailingMessages shouldn't be too hard.
     
  17. Warnecke

    Warnecke

    Unity Technologies

    Joined:
    Nov 28, 2017
    Posts:
    92
    We are working on something for this. It will allow you to split the building of the player from the actual run, thus being able to do the build on a machine without the device and then copy the resulting player to a device/a machine with the device and execute it. We then have some hooks that will allow you to process the test result yourself.
     
    ModLunar and 5argon like this.
  18. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    This would be great to send the build to Firebase Test Labs devices. Will the build be compatible with XCTest as well? Since it seems to be a framework Firebase Test Labs supports for iOS build.

    A small suggestion, please allow any bundle name other than com.UnityTestRunner.UnityTestRunner. It affects Firebase library in particular and I have to make a new Firebase project with this bundle name and have to manually switch in a custom credential because this lib compares bundle name.
     
  19. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    For those following this thread - check out my new Unity Test Extensions project on GitHub.
    It contains the LogAssertEx class that provides some improvements that were missing in the original LogAssert.

    Right now it offers basic improvements, but will keep on getting more stuff soon :)
     
    glenneroo likes this.
  20. Deleted User

    Deleted User

    Guest

    Wow, that's 3999935 more tests than I run! I think I'm almost catching up :p

    Is there a way to use LogAssert, but have a clear console at the end of the test? I have a function that logs an error when you use it wrong, and a test that uses LogAssert.Expect to make sure the error is logged, but it's cluttering the debug console every time I run the full test suite. It seems like "pull the error I just checked for out of the log" would be a useful command, at least for my workflow. Maybe it exists and I'm just using it wrong. As liortal said:
    I had the honor of posting the first LogAssert question on the Answers site (as far as my search turned up), but I haven't had much luck there, so I thought I'd bomb the suggestion thread here as well. :D
    (Just re-reading the thread, I noticed that this question was already brought up. Bump!)
     
  21. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    You quoted me, so i came :)

    Just out of general curiousity - why do you care so much about the console at the end of your tests?

    Errors that appear there were expected, otherwise they sould fail the test.

    You want to filter the console from expected messages? I think that you could implement something like this yourself by implementing the ILogger interface.
     
  22. pwdstaraster

    pwdstaraster

    Joined:
    Nov 11, 2020
    Posts:
    3
    It would be great if there were a way to only have to handle Errors and Asserts, and ignore Logs when using LogAssert. Our log is verbose, and when I'm expecting an error, I have to register a lot (too many) of Log type logs.
     
    ActiveSim likes this.
  23. ActiveSim

    ActiveSim

    Joined:
    May 10, 2019
    Posts:
    59
    I would like to have a LogAssert.Contains (like Assert.Contains) if not the complete log message is know. Is there any way to do that with the current features that I haven't seen?
     
  24. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    LogAssert allows using a regex from what i remember. This sounds like what you need...
     
    ActiveSim likes this.
  25. ActiveSim

    ActiveSim

    Joined:
    May 10, 2019
    Posts:
    59
    Could you please give an example, e.g. here?
     
  26. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    @ActiveSim Here's an example of what i meant:
    Code (CSharp):
    1. LogAssert.Expect(LogType.Exception, new Regex("Assertion failure.*"));
    This assertion will catch all cases of an exception with the text containing "Assertion failure", but doesn't have to match it precisely.
     
    ActiveSim likes this.
  27. dschilens

    dschilens

    Joined:
    May 21, 2018
    Posts:
    1
    More fun: you can't stuff the
    LogAssert.ignoreFailingMessages = true
    call into a SetUp function. By the time any log calls happen in your test, it will have been reset back to false. Manually putting that line into each test works, so if you have multiple tests where you're expecting errors you have to call this for each test.

    This is not documented, and totally unexpected. What's the point of setting a global "don't mess with my tests" if it resets itself?
     
    ActiveSim likes this.
  28. Mike99

    Mike99

    Joined:
    Dec 11, 2011
    Posts:
    160
    is it me or the LogAssert.Expect doesn't work with Debug.LogError ? (Unity 2021.1.27f1 - Win)
    it works fine if I use Debug.Log but not with Debug.LogError...
     
  29. ActiveSim

    ActiveSim

    Joined:
    May 10, 2019
    Posts:
    59
    It works well for me. Did your code look like:
    Code (CSharp):
    1. LogAssert.Expect(LogType.Error, "your log content");
    and is
    Code (CSharp):
    1.             LogAssert.ignoreFailingMessages = false;
     
  30. MiguelKing

    MiguelKing

    Joined:
    Apr 28, 2015
    Posts:
    5
    The original suggestion of this post, to add a LogAssert.Expect where you can specify "Any number of times" would be really useful. Any news since it was proposed back in 2018?
     
  31. unity_88F5AD6843FE4D865395

    unity_88F5AD6843FE4D865395

    Joined:
    Dec 8, 2021
    Posts:
    3
    +1 to this
     
  32. AdamBebkoSL

    AdamBebkoSL

    Joined:
    Dec 9, 2021
    Posts:
    33
    It seems in the Expect() method, There's no option for ANY string message. I tried using NSubstitute's Arg.Any<string>() but no dice. It would be great to have an option to not care about what the message is.
     
  33. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    It also takes a regex, just set it to match any string...
    Code (CSharp):
    1. LogAssert.Expect(new Regex(".+"));
     
  34. AdamBebkoSL

    AdamBebkoSL

    Joined:
    Dec 9, 2021
    Posts:
    33
    Thanks. That's helpful! Although it assumes you know how to Regex.. haha. I'm happy to copy paste that though!
     
  35. Sergey_OneUp_Games

    Sergey_OneUp_Games

    Joined:
    Aug 4, 2021
    Posts:
    4
    Hi all!

    Seting
    LogAssert.IgnoreFailingMessages = true
    in a
    [SetUp]
    method not working as expected for PlayMode tests.

    Under the hood
    LogScope
    exists in many instances with
    IgnoreFailingMessages = false
    by default.
    Any call
    LogAssert.IgnoreFailingMessages = true
    change the property only for "current" instance of
    LogSope
    .

    If your game log any error at startup you will always getting failed test run with "Unhandled log message"!
    LogScope
    u have no chance to set
    LogAssert.IgnoreFailingMessages = true
    for instance of that
    LogSope
    .

    Actual for Test Framework 2.0.1-exp.2

    ---
    As quick fix you can intro real static property for
    LogAssert.IgnoreFailingMessages
    and check tham in any
    LogScope
     
    Last edited: Mar 6, 2023