Bradley Geschrieben 13. Januar 2020 Melden Share Geschrieben 13. Januar 2020 Ich will meinen Code etwas solider gestalten und versuche mich gerade in die Unittests mit Monobehaivour heran zu tasten. Im Moment scheitere ich aber schon daran überhaupt mein Script aufgerufen zu bekommen: public void CheckTextInTooltip() { bool result = false; ToolTipText toolTip = gameObject.AddComponent(typeof(ToolTipText)) as ToolTipText; result = toolTip.ToolTipTextInputCheck(""); Assert.IsFalse(result); } Der Editor verkündet immer ein NullReference Error. Dass ich solche Klassen nicht einfach mit New Instanziieren kann ist mir mittlerweile klar. Eine weitere Frage: Kann ich diese Unittests auch automatisiert in Azure DevOps testen lassen? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 13. Januar 2020 Melden Share Geschrieben 13. Januar 2020 Unity hat ein eigenes Test-Framework, das teilweise auf NUnit basiert. Schau dir dazu einfach mal die verfügbaren Tutorials an. Warum da jetzt eine NullReferenceException kommt, ist schwer zu sagen. AddComponent sieht richtig aus (auch wenn die generische Version etwas schlanker ist). Fliegt die Exception denn in der "result = "-Zeile? Ansonsten könnte höchstens noch, je nach dem wie hier der Kontext ist, gameObject null sein. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Bradley Geschrieben 14. Januar 2020 Autor Melden Share Geschrieben 14. Januar 2020 Tatsächlich fliegt der Fehler schon bei: ToolTipText toolTip = gameObject.AddComponent(typeof(ToolTipText)) as ToolTipText; Der genau Fehlertext: Zitat CheckTextInTooltip (0,001s) --- System.NullReferenceException : --- at (wrapper managed-to-native) UnityEngine.Component.get_gameObject(UnityEngine.Component) at Tests.ToolTipWindow_Test.CheckTextInTooltip () [0x00003] in C:\Users\xxxxxx\Documents\SpaceOperaUnity\Assets\SpaceOpera\Tests\ToolTipWindow_Test.cs:16 at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <567df3e0919241ba98db88bec4c6696f>:0 Ich hänge mal die Entsprechende (noch schlampig aussehende) Klasse an. using UnityEngine; using UnityEngine.UI; public class ToolTipText : MonoBehaviour { [Header("Einstellungen")] [Tooltip("Zeit in Sekunden bis das Tooltip erscheint")] [Range(0.0f, 5.0f)] public float targetTime = 1.5f; [Tooltip("Gibt an ob das Tooltip per Default Aktiv ist")] public bool ToolTipAktiv = true; [Tooltip("Gibt an ob das Tooltip aktuell aktiv ist oder nicht")] public bool ToolTipVisible = false; [Header("Zuweisungen")] public Text toolTipText; public GameObject toolTipPanel; [SerializeField] private float deltaTimer = 0.0f; Vector3 MousCordOffset = new Vector3(0, 0, 0); private void Start() { } public void ToolTip(string Text) { toolTipText.text = Text; } public void Update() { if (ToolTipAktiv) { ToolTipVisible = ToolTipTextInputCheck(toolTipText.text); toolTipPanel.gameObject.transform.position = ShowToolTip(ToolTipVisible); Debug.Log(toolTipPanel.gameObject.transform.position); //if (!ToolTipVisible) //{ // deltaTimer -= Time.deltaTime; // if (deltaTimer <= 0.0f) // { // ToolTipVisible = true; // } //} //else //{ // MousCordOffset.x = Input.mousePosition.x + 20; // MousCordOffset.y = Input.mousePosition.y + 00; // toolTipPanel.gameObject.transform.position = MousCordOffset; //} } } /// <summary> /// In abhängigkeit vom Text wird True oder False zurück gegeben /// </summary> /// <param name="text">Text kommt vom tooltip.text</param> /// <returns>Ist text leer, wird False zurück gegeben. Sonst True</returns> public bool ToolTipTextInputCheck(string text) { if (text.Length == 0 || text == null) { toolTipPanel.gameObject.transform.position = new Vector3(-500, -500, 0); deltaTimer = targetTime; return false; } return true; } private Vector3 ShowToolTip(bool toolTipVisible) { if (!toolTipVisible) { deltaTimer -= Time.deltaTime; if (deltaTimer <= 0.0f) { ToolTipVisible = true; } return new Vector3(-500, -500, 0); } else { MousCordOffset.x = Input.mousePosition.x + 20; MousCordOffset.y = Input.mousePosition.y + 00; return MousCordOffset; } } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 14. Januar 2020 Melden Share Geschrieben 14. Januar 2020 Viel interessanter wäre die Klasse ToolTipWindow_Test. Ich gehe einfach mal davon aus, dass das keine MonoBehaviour-Klasse ist und du daher die Variable "gameObject" selbst definiert hast. Stimmt das? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Bradley Geschrieben 14. Januar 2020 Autor Melden Share Geschrieben 14. Januar 2020 Tatsächlich ist Sie eine. using System.Collections; using System.Collections.Generic; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; namespace Tests { public class ToolTipWindow_Test : MonoBehaviour { [Test] public void CheckTextInTooltip() { bool result = false; ToolTipText toolTip = gameObject.AddComponent(typeof(ToolTipText)) as ToolTipText; result = toolTip.ToolTipTextInputCheck(""); Assert.IsFalse(result); } } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 14. Januar 2020 Melden Share Geschrieben 14. Januar 2020 Ah, aber du startest die Methode über das Testframework. Ich weiß nicht genau, was das Ding macht, aber irgendetwas sagt mir, dass deine Komponente sich nicht auf einem GameObject befindet. Tests packst du auch einfach nicht in MonoBehaviours. Nimm also die Superklasse da raus und baue dir für den Test ein GameObject. private GameObject gameObject; [SetUp] public void Setup() { gameObject = new GameObject("Test Object"); } Denke auch daran, das Ding wieder zu zerstören: [TearDown] public void Teardown() { Object.Destroy(gameObject); } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Bradley Geschrieben 15. Januar 2020 Autor Melden Share Geschrieben 15. Januar 2020 Erstmal danke an dich Sascha. Ich bin jetzt mal ein Schritt weiter gekommen: public class ToolTipWindow_Test : MonoBehaviour { private GameObject toolTip; [SetUp] public void Setup() { toolTip = new GameObject("Panel_ToolTip"); toolTip.gameObject.AddComponent<ToolTipText>(); //toolTip.GetComponent<ToolTipText>().Start(); toolTip.GetComponent<ToolTipText>().toolTipText = gameObject.AddComponent<Text>(); toolTip.GetComponent<ToolTipText>().toolTipPanel = new GameObject("Panel"); } [Test] public void CheckTextInTooltip_False() { bool result = false; result = toolTip.GetComponent<ToolTipText>().ToolTipTextInputCheck(""); Assert.IsFalse(result); } [Test] public void CheckTextInTooltip_True() { bool result = false; result = toolTip.GetComponent<ToolTipText>().ToolTipTextInputCheck("TEST"); Assert.IsTrue(result); } [TearDown] public void Teardown() { Object.DestroyImmediate(toolTip); } } Einziges Problem, das ich noch habe ist folgender Abschnitt: toolTip.GetComponent<ToolTipText>().toolTipText = gameObject.AddComponent<Text>(); Lagere ich das ganze in eine Funktion aus welche in der zu testenden Klasse ist, und rufe die Funktion im Setup auf, habe ich kein Problem mehr. Ich wollte das ganze allerdings auch das ganze in der TestSetup machen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.