< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
KMeansClustererTests()0%2100%
GenerateObject(...)0%2100%
TestSingleCluster()0%2100%
TestTwoDistinctClustersWithResetNeeded()0%42600%

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 {
 09  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
 016  public static GameObject GenerateObject(in Vector3 position) {
 017    GameObject obj = new GameObject();
 018    Agent agent = obj.AddComponent<DummyAgent>();
 019    obj.transform.position = position;
 020    return obj;
 021  }
 22
 23  [Test]
 024  public void TestSingleCluster() {
 025    KMeansClusterer clusterer = new KMeansClusterer(Objects, k: 1);
 026    clusterer.Cluster();
 027    Cluster cluster = clusterer.Clusters[0];
 028    Assert.AreEqual(Objects.Count, cluster.Size());
 029    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Coordinates);
 030    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Centroid());
 031  }
 32
 33  // Test to reveal improper clearing of cluster memberships.
 34  [Test]
 035  public void TestTwoDistinctClustersWithResetNeeded() {
 36    // Group A: points near (0, 0, 0).
 037    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).
 045    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.
 053    var objects = new List<GameObject>();
 054    objects.AddRange(groupA);
 055    objects.AddRange(groupB);
 56
 57    // Create clusterer with k = 2.
 058    KMeansClusterer clusterer = new KMeansClusterer(objects, k: 2);
 059    clusterer.Cluster();
 60
 61    // We expect exactly 2 clusters.
 062    Assert.AreEqual(2, clusterer.Clusters.Count);
 63
 64    // Retrieve the clusters.
 065    Cluster c0 = clusterer.Clusters[0];
 066    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.
 070    var centroid0 = c0.Centroid();
 071    var centroid1 = c1.Centroid();
 72
 73    // One centroid should be near (0.5, 0.5, 0), the other near (10.5, 10.5, 10).
 074    var expectedCentroid0 = new Vector3(0.5f, 0.5f, 0);
 075    var expectedCentroid1 = new Vector3(10.5f, 10.5f, 10);
 076    bool correctPlacement = (centroid0 == expectedCentroid0 && centroid1 == expectedCentroid1) ||
 77                            (centroid0 == expectedCentroid1 && centroid1 == expectedCentroid0);
 078    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.
 084    int cluster0Count = c0.Size();
 085    int cluster1Count = c1.Size();
 086    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.
 091    bool clusterCountsValid = cluster0Count == 4 && cluster1Count == 4;
 092    Assert.IsTrue(clusterCountsValid,
 93                  $"Cluster sizes not as expected. c0={cluster0Count}, c1={cluster1Count}.");
 094  }
 95}
 96
 97public class ConstrainedKMeansClustererTests {
 98  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
 105  public static GameObject GenerateObject(in Vector3 position) {
 106    GameObject obj = new GameObject();
 107    Agent agent = obj.AddComponent<DummyAgent>();
 108    obj.transform.position = position;
 109    return obj;
 110  }
 111
 112  [Test]
 113  public void TestSingleCluster() {
 114    ConstrainedKMeansClusterer clusterer =
 115        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: Mathf.Infinity);
 116    clusterer.Cluster();
 117    Assert.AreEqual(1, clusterer.Clusters.Count);
 118    Cluster cluster = clusterer.Clusters[0];
 119    Assert.AreEqual(Objects.Count, cluster.Size());
 120    Assert.AreEqual(new Vector3(0, 1.25f, 0), cluster.Centroid());
 121  }
 122
 123  [Test]
 124  public void TestMaxSizeOne() {
 125    ConstrainedKMeansClusterer clusterer =
 126        new ConstrainedKMeansClusterer(Objects, maxSize: 1, maxRadius: Mathf.Infinity);
 127    clusterer.Cluster();
 128    Assert.AreEqual(Objects.Count, clusterer.Clusters.Count);
 129    foreach (var cluster in clusterer.Clusters) {
 130      Assert.AreEqual(1, cluster.Size());
 131    }
 132  }
 133
 134  [Test]
 135  public void TestZeroRadius() {
 136    ConstrainedKMeansClusterer clusterer =
 137        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: 0);
 138    clusterer.Cluster();
 139    Assert.AreEqual(Objects.Count, clusterer.Clusters.Count);
 140    foreach (var cluster in clusterer.Clusters) {
 141      Assert.AreEqual(1, cluster.Size());
 142    }
 143  }
 144
 145  [Test]
 146  public void TestSmallRadius() {
 147    ConstrainedKMeansClusterer clusterer =
 148        new ConstrainedKMeansClusterer(Objects, maxSize: Objects.Count, maxRadius: 1);
 149    clusterer.Cluster();
 150    Assert.AreEqual(2, clusterer.Clusters.Count);
 151  }
 152}