< Summary

Class:DCL.Helpers.AssetBundlesVisualTestHelpers
Assembly:AssetBundlesVisualTestHelpers
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/ABConverter/VisualTests/AssetBundlesVisualTestHelpers.cs
Covered lines:0
Uncovered lines:105
Coverable lines:105
Total lines:261
Line coverage:0% (0 of 105)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AssetBundlesVisualTestHelpers()0%2100%
TakeSnapshot()0%1101000%
TestSnapshot(...)0%20400%
TakeSnapshot()0%1321100%
ComputeImageAffinityPercentage(...)0%2100%
ComputeImageAffinityPercentage(...)0%90900%
DuplicateTextureAsReadable(...)0%2100%
IsSamePixel(...)0%42600%
RepositionVisualTestsCamera(...)0%12300%
RepositionVisualTestsCamera(...)0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/ABConverter/VisualTests/AssetBundlesVisualTestHelpers.cs

#LineLine coverage
 1using DCL.Configuration;
 2using System.Collections;
 3using System.IO;
 4using UnityEngine;
 5using UnityEngine.Assertions;
 6
 7namespace DCL.Helpers
 8{
 9    /// <summary>
 10    /// Visual tests helper class used to validate Asset Bundle conversions. Based on 'Scripts/Tests/VisualTests/VisualT
 11    /// </summary>
 12    public static class AssetBundlesVisualTestHelpers
 13    {
 014        public static string testImagesPath = Application.dataPath + "/../TestResources/VisualTests/CurrentTestImages/";
 15
 016        public static string baselineImagesPath = Application.dataPath + "/../TestResources/VisualTests/BaselineImages/"
 17
 018        public static bool generateBaseline = false;
 19
 20        public static IEnumerator TakeSnapshot(string snapshotName, Camera camera, Vector3? shotPosition = null, Vector3
 21        {
 022            if (shotPosition.HasValue || shotTarget.HasValue)
 23            {
 024                RepositionVisualTestsCamera(camera, shotPosition, shotTarget);
 25            }
 26
 027            yield return null;
 028            yield return null;
 29
 030            int snapshotsWidth = TestSettings.VISUAL_TESTS_SNAPSHOT_WIDTH;
 031            int snapshotsHeight = TestSettings.VISUAL_TESTS_SNAPSHOT_HEIGHT;
 32
 033            if (generateBaseline || !File.Exists(baselineImagesPath + snapshotName))
 34            {
 035                yield return TakeSnapshot(baselineImagesPath, snapshotName, camera,
 36                    snapshotsWidth, snapshotsHeight);
 037            }
 38            else
 39            {
 040                yield return TakeSnapshot(testImagesPath, snapshotName, camera, snapshotsWidth, snapshotsHeight);
 41            }
 042        }
 43
 44        public static bool TestSnapshot(string baselineImagePathWithFilename, string testImagePathWithFilename, float ra
 45        {
 046            if (generateBaseline || !File.Exists(baselineImagePathWithFilename))
 047                return false;
 48
 049            float ratioResult =
 50                ComputeImageAffinityPercentage(baselineImagePathWithFilename, testImagePathWithFilename);
 51
 052            if (assert)
 53            {
 054                Assert.IsTrue(ratioResult > ratio,
 55                    $"{Path.GetFileName(baselineImagePathWithFilename)} has {ratioResult}% affinity, the minimum is {rat
 56            }
 57
 058            return ratioResult > ratio;
 59        }
 60
 61        /// <summary>
 62        /// This coroutine will take a visual test snapshot using the camera provided, with the given image size.
 63        /// The image will be saved to disk as png.
 64        /// </summary>
 65        /// <param name="snapshotPath">Path to the directory where the image will be saved. Will be created if not exist
 66        /// <param name="snapshotName">output filename, it should include the png extension</param>
 67        /// <param name="camera">camera used to take the shot</param>
 68        /// <param name="width">Width of the final image</param>
 69        /// <param name="height">Height of the final image</param>
 70        public static IEnumerator TakeSnapshot(string snapshotPath, string snapshotName, Camera camera, int width,
 71            int height)
 72        {
 073            if (string.IsNullOrEmpty(snapshotName) || camera == null)
 74            {
 075                Debug.Log("snapshot name or camera is not valid. Snapshot aborted.");
 076                yield break;
 77            }
 78
 079            var previousQualityLevel = QualitySettings.GetQualityLevel();
 080            QualitySettings.SetQualityLevel((int) QualityLevel.Good, true);
 81
 082            string finalPath = snapshotPath + snapshotName;
 83
 084            if (File.Exists(finalPath))
 85            {
 086                File.Delete(finalPath);
 87
 88                // Just in case, wait until the file is deleted
 089                yield return new WaitUntil(() => { return !File.Exists(finalPath); });
 90            }
 91
 92            // We should only read the screen buffer after rendering is complete
 093            yield return null;
 94
 095            RenderTexture renderTexture = new RenderTexture(width, height, 24);
 096            camera.targetTexture = renderTexture;
 097            camera.Render();
 98
 099            RenderTexture.active = renderTexture;
 0100            Texture2D currentSnapshot = new Texture2D(width, height, TextureFormat.RGB24, false);
 0101            currentSnapshot.ReadPixels(new Rect(0, 0, width, height), 0, 0);
 0102            currentSnapshot.Apply();
 103
 0104            yield return null;
 105
 0106            if (!Directory.Exists(snapshotPath))
 107            {
 0108                Directory.CreateDirectory(snapshotPath);
 109            }
 110
 0111            byte[] bytes = currentSnapshot.EncodeToPNG();
 0112            File.WriteAllBytes(finalPath, bytes);
 113
 114            // Just in case, wait until the file is created
 0115            yield return new WaitUntil(() => { return File.Exists(finalPath); });
 116
 0117            RenderTexture.active = null;
 0118            renderTexture.Release();
 119
 0120            yield return new WaitForSeconds(0.2f);
 121
 0122            QualitySettings.SetQualityLevel(previousQualityLevel, true);
 0123        }
 124
 125        public static float ComputeImageAffinityPercentage(string baselineImagePathWithFilename,
 126            string testImagePathWithFilename)
 127        {
 0128            Texture2D baselineSnapshot = new Texture2D(TestSettings.VISUAL_TESTS_SNAPSHOT_WIDTH,
 129                TestSettings.VISUAL_TESTS_SNAPSHOT_HEIGHT, TextureFormat.RGB24, false);
 0130            baselineSnapshot.LoadImage(File.ReadAllBytes(baselineImagePathWithFilename));
 131
 0132            Texture2D currentSnapshot = new Texture2D(TestSettings.VISUAL_TESTS_SNAPSHOT_WIDTH,
 133                TestSettings.VISUAL_TESTS_SNAPSHOT_HEIGHT, TextureFormat.RGB24, false);
 0134            currentSnapshot.LoadImage(File.ReadAllBytes(testImagePathWithFilename));
 135
 0136            string finalDiffPath = Path.GetDirectoryName(testImagePathWithFilename) + "/" +
 137                                   Path.GetFileNameWithoutExtension(testImagePathWithFilename) + "_diff" +
 138                                   Path.GetExtension(testImagePathWithFilename);
 139
 0140            return ComputeImageAffinityPercentage(baselineSnapshot, currentSnapshot, finalDiffPath);
 141        }
 142
 143        /// <summary>
 144        /// This will compare the pixels of two images in order to make visual tests.
 145        /// </summary>
 146        /// <param name="baselineImage">Reference or "golden" image</param>
 147        /// <param name="testImage">Image to compare</param>
 148        /// <param name="diffImagePath"></param>
 149        /// <returns>Affinity percentage</returns>
 150        public static float ComputeImageAffinityPercentage(Texture2D baselineImage, Texture2D testImage,
 151            string diffImagePath)
 152        {
 0153            baselineImage = DuplicateTextureAsReadable(baselineImage);
 0154            testImage = DuplicateTextureAsReadable(testImage);
 155
 0156            if (string.IsNullOrEmpty(diffImagePath))
 157            {
 0158                Debug.Log("diff image path is not valid. Image affinity percentage check aborted.");
 159
 0160                return -1;
 161            }
 162
 0163            if (baselineImage.width != testImage.width || baselineImage.height != testImage.height)
 164            {
 0165                Debug.Log("CAN'T COMPARE IMAGES WITH DIFFERENT DIMENSIONS:");
 0166                Debug.Log("baseline image dimensions: " + baselineImage.width + "," + baselineImage.height);
 0167                Debug.Log("test image dimensions: " + testImage.width + "," + testImage.height);
 168
 0169                return -1;
 170            }
 171
 0172            Color32[] baselineImagePixels = baselineImage.GetPixels32();
 0173            Color32[] testImagePixels = testImage.GetPixels32();
 0174            Color32[] diffImagePixels = new Color32[testImagePixels.Length];
 0175            Color32 diffColor = new Color32(255, 0, 0, 255);
 0176            int differentPixels = 0;
 177
 0178            for (int i = 0; i < testImagePixels.Length; i++)
 179            {
 0180                if (!IsSamePixel(testImagePixels[i], baselineImagePixels[i],
 181                    TestSettings.VISUAL_TESTS_PIXELS_CHECK_THRESHOLD))
 182                {
 0183                    differentPixels++;
 0184                    diffImagePixels[i] = diffColor;
 0185                }
 186                else
 187                {
 0188                    diffImagePixels[i] = baselineImagePixels[i];
 189                }
 190            }
 191
 192            // Calculate Image Affinity
 0193            float imageAffinity = ((testImagePixels.Length - differentPixels) * 100) / testImagePixels.Length;
 194
 195            // Save diff image
 0196            if (imageAffinity < TestSettings.VISUAL_TESTS_APPROVED_AFFINITY)
 197            {
 0198                Texture2D diffImage = new Texture2D(baselineImage.width, baselineImage.height);
 0199                diffImage.SetPixels32(diffImagePixels);
 0200                diffImage.Apply();
 0201                byte[] bytes = diffImage.EncodeToPNG();
 0202                File.WriteAllBytes(diffImagePath, bytes);
 0203            }
 0204            else if (File.Exists(diffImagePath))
 205            {
 0206                File.Delete(diffImagePath);
 207
 0208                if (File.Exists(diffImagePath + ".meta"))
 0209                    File.Delete(diffImagePath + ".meta");
 210            }
 211
 0212            return imageAffinity;
 213        }
 214
 215        public static Texture2D DuplicateTextureAsReadable(Texture2D source)
 216        {
 0217            RenderTexture renderTex = RenderTexture.GetTemporary(
 218                source.width,
 219                source.height,
 220                0,
 221                RenderTextureFormat.Default,
 222                RenderTextureReadWrite.Linear);
 223
 0224            Graphics.Blit(source, renderTex);
 225
 0226            RenderTexture previous = RenderTexture.active;
 0227            RenderTexture.active = renderTex;
 228
 0229            Texture2D readableText = new Texture2D(source.width, source.height);
 0230            readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
 0231            readableText.Apply();
 232
 0233            RenderTexture.active = previous;
 0234            RenderTexture.ReleaseTemporary(renderTex);
 235
 0236            return readableText;
 237        }
 238
 239        public static bool IsSamePixel(Color32 pixelA, Color32 pixelB, float checkThreshold)
 240        {
 0241            return (pixelA.r > pixelB.r - checkThreshold && pixelA.r < pixelB.r + checkThreshold) &&
 242                   (pixelA.g > pixelB.g - checkThreshold && pixelA.g < pixelB.g + checkThreshold) &&
 243                   (pixelA.b > pixelB.b - checkThreshold && pixelA.b < pixelB.b + checkThreshold);
 244        }
 245
 246        public static void RepositionVisualTestsCamera(Transform cameraTransform, Vector3? position = null, Vector3? tar
 247        {
 0248            if (position.HasValue)
 249            {
 0250                cameraTransform.position = position.Value;
 251            }
 252
 0253            if (target.HasValue)
 254            {
 0255                cameraTransform.forward = target.Value - cameraTransform.position;
 256            }
 0257        }
 258
 0259        public static void RepositionVisualTestsCamera(Camera camera, Vector3? position = null, Vector3? target = null) 
 260    }
 261}