< Summary

Class:ConstrainedKMeansClustererTests
Assembly:bamlab.test.editmode
File(s):/github/workspace/Assets/Tests/EditMode/KMeansClustererTests.cs
Covered lines:0
Uncovered lines:36
Coverable lines:36
Total lines:152
Line coverage:0% (0 of 36)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:6
Method coverage:0% (0 of 6)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ConstrainedKMeansClustererTests()0%2100%
GenerateObject(...)0%2100%
TestSingleCluster()0%2100%
TestMaxSizeOne()0%12300%
TestZeroRadius()0%12300%
TestSmallRadius()0%2100%

File(s)

/github/workspace/Assets/Tests/EditMode/KMeansClustererTests.cs

#LineLine coverage
 1using NUnit.Framework;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using UnityEngine;
 6using UnityEngine.TestTools;
 7
 8public class KMeansClustererTests {
 9  public static readonly List<GameObject> Objects = new List<GameObject> {
 10    GenerateObject(new Vector3(0, 0, 0)),
 11    GenerateObject(new Vector3(0, 1, 0)),
 12    GenerateObject(new Vector3(0, 1.5f, 0)),
 13    GenerateObject(new Vector3(0, 2.5f, 0)),
 14  };
 15
 16  public static GameObject GenerateObject(in Vector3 position) {
 17    GameObject obj = new GameObject();
 18    Agent agent = obj.AddComponent<DummyAgent>();
 19    obj.transform.position = position;
 20    return obj;
 21  }
 22
 23  [Test]
 24  public void TestSingleCluster() {
 25    KMeansClusterer clusterer = new KMeansClusterer(Objects, k: 1);
 26    clusterer.Cluster();
 27    Cluster cluster = clusterer.Clusters[0];
 28    Assert.AreEqual(Objects.Count, cluster.Size());
 29    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Coordinates);
 30    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Centroid());
 31  }
 32
 33  // Test to reveal improper clearing of cluster memberships.
 34  [Test]
 35  public void TestTwoDistinctClustersWithResetNeeded() {
 36    // Group A: points near (0, 0, 0).
 37    var groupA = new List<GameObject> {
 38      GenerateObject(new Vector3(0, 0, 0)),
 39      GenerateObject(new Vector3(1, 0, 0)),
 40      GenerateObject(new Vector3(0, 1, 0)),
 41      GenerateObject(new Vector3(1, 1, 0)),
 42    };
 43
 44    // Group B: points near (10, 10, 10).
 45    var groupB = new List<GameObject> {
 46      GenerateObject(new Vector3(10, 10, 10)),
 47      GenerateObject(new Vector3(11, 10, 10)),
 48      GenerateObject(new Vector3(10, 11, 10)),
 49      GenerateObject(new Vector3(11, 11, 10)),
 50    };
 51
 52    // Combine them.
 53    var objects = new List<GameObject>();
 54    objects.AddRange(groupA);
 55    objects.AddRange(groupB);
 56
 57    // Create clusterer with k = 2.
 58    KMeansClusterer clusterer = new KMeansClusterer(objects, k: 2);
 59    clusterer.Cluster();
 60
 61    // We expect exactly 2 clusters.
 62    Assert.AreEqual(2, clusterer.Clusters.Count);
 63
 64    // Retrieve the clusters.
 65    Cluster c0 = clusterer.Clusters[0];
 66    Cluster c1 = clusterer.Clusters[1];
 67
 68    // Because the clusters are well-separated, each cluster should contain all points from one
 69    // group or the other, not a mixture. Check via centroids.
 70    var centroid0 = c0.Centroid();
 71    var centroid1 = c1.Centroid();
 72
 73    // One centroid should be near (0.5, 0.5, 0), the other near (10.5, 10.5, 10).
 74    var expectedCentroid0 = new Vector3(0.5f, 0.5f, 0);
 75    var expectedCentroid1 = new Vector3(10.5f, 10.5f, 10);
 76    bool correctPlacement = (centroid0 == expectedCentroid0 && centroid1 == expectedCentroid1) ||
 77                            (centroid0 == expectedCentroid1 && centroid1 == expectedCentroid0);
 78    Assert.IsTrue(
 79        correctPlacement,
 80        "Centroids not close to the expected group centers. Possible leftover membership from a previous iteration if cl
 81
 82    // Additionally, we can count membership to confirm that each cluster got exactly four points
 83    // for a more direct check.
 84    int cluster0Count = c0.Size();
 85    int cluster1Count = c1.Size();
 86    Assert.AreEqual(8, cluster0Count + cluster1Count,
 87                    "Total membership across clusters does not match the total number of objects.");
 88
 89    // Even if the clusters swapped roles, each cluster should have 4 points if membership was
 90    // properly reset and re-assigned.
 91    bool clusterCountsValid = cluster0Count == 4 && cluster1Count == 4;
 92    Assert.IsTrue(clusterCountsValid,
 93                  $"Cluster sizes not as expected. c0={cluster0Count}, c1={cluster1Count}.");
 94  }
 95}
 96
 97public class ConstrainedKMeansClustererTests {
 098  public static readonly List<GameObject> Objects = new List<GameObject> {
 99    GenerateObject(new Vector3(0, 0, 0)),
 100    GenerateObject(new Vector3(0, 1, 0)),
 101    GenerateObject(new Vector3(0, 1.5f, 0)),
 102    GenerateObject(new Vector3(0, 2.5f, 0)),
 103  };
 104
 0105  public static GameObject GenerateObject(in Vector3 position) {
 0106    GameObject obj = new GameObject();
 0107    Agent agent = obj.AddComponent<DummyAgent>();
 0108    obj.transform.position = position;
 0109    return obj;
 0110  }
 111
 112  [Test]
 0113  public void TestSingleCluster() {
 0114    ConstrainedKMeansClusterer clusterer =
 115        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: Mathf.Infinity);
 0116    clusterer.Cluster();
 0117    Assert.AreEqual(1, clusterer.Clusters.Count);
 0118    Cluster cluster = clusterer.Clusters[0];
 0119    Assert.AreEqual(Objects.Count, cluster.Size());
 0120    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Centroid());
 0121  }
 122
 123  [Test]
 0124  public void TestMaxSizeOne() {
 0125    ConstrainedKMeansClusterer clusterer =
 126        new ConstrainedKMeansClusterer(Objects, maxSize: 1, maxRadius: Mathf.Infinity);
 0127    clusterer.Cluster();
 0128    Assert.AreEqual(Objects.Count, clusterer.Clusters.Count);
 0129    foreach (var cluster in clusterer.Clusters) {
 0130      Assert.AreEqual(1, cluster.Size());
 0131    }
 0132  }
 133
 134  [Test]
 0135  public void TestZeroRadius() {
 0136    ConstrainedKMeansClusterer clusterer =
 137        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: 0);
 0138    clusterer.Cluster();
 0139    Assert.AreEqual(Objects.Count, clusterer.Clusters.Count);
 0140    foreach (var cluster in clusterer.Clusters) {
 0141      Assert.AreEqual(1, cluster.Size());
 0142    }
 0143  }
 144
 145  [Test]
 0146  public void TestSmallRadius() {
 0147    ConstrainedKMeansClusterer clusterer =
 148        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: 1);
 0149    clusterer.Cluster();
 0150    Assert.AreEqual(2, clusterer.Clusters.Count);
 0151  }
 152}