From 3e5a92ac911189b46989f0b112fab01b495db3e7 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Wed, 14 Feb 2024 11:11:22 +0100 Subject: [PATCH] [FEAT] All tests is now in BDD Style (like the book) --- tests/05_rays.cpp | 500 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 385 insertions(+), 115 deletions(-) diff --git a/tests/05_rays.cpp b/tests/05_rays.cpp index 9549590..8a59620 100644 --- a/tests/05_rays.cpp +++ b/tests/05_rays.cpp @@ -119,182 +119,406 @@ SCENARIO("A ray intersects a sphere at two points", "[features/spheres.feature]" SCENARIO("A ray intersects a sphere at a tangent", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 1, -5), Tuple::Vector(0, 0, 1)); - Sphere s; - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].distance_t() == 5.0); - REQUIRE(xs[1].distance_t() == 5.0); + GIVEN("r <- ray(point(0, 0, -5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 1, -5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- sphere()") + { + Sphere s; + WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0] = 5.0") + { + REQUIRE(xs[0].distance_t() == 5.0); + } + AND_THEN("xs[1] = 5.0") + { + REQUIRE(xs[1].distance_t() == 5.0); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("A ray misses a sphere", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 2, -5), Tuple::Vector(0, 0, 1)); - Sphere s; - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 0); + GIVEN("r <- ray(point(0, 2, -5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 2, -5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- sphere()") + { + Sphere s; + WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 0") + { + REQUIRE(xs.count() == 0); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("A originates inside a sphere", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 0, 1)); - Sphere s; - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].distance_t() == -1.0); - REQUIRE(xs[1].distance_t() == 1.0); + GIVEN("r <- ray(point(0, 0, 0), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- sphere()") + { + Sphere s; + WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0] = -1.0") + { + REQUIRE(xs[0].distance_t() == -1.0); + } + AND_THEN("xs[1] = 1.0") + { + REQUIRE(xs[1].distance_t() == 1.0); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("A sphere is behind a ray", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); - Sphere s; - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].distance_t() == -6.0); - REQUIRE(xs[1].distance_t() == -4.0); + GIVEN("r <- ray(point(0, 0, 5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- sphere()") + { + Sphere s; + WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0] = -6.0") + { + REQUIRE(xs[0].distance_t() == -6.0); + } + AND_THEN("xs[1] = -4.0)") + { + REQUIRE(xs[1].distance_t() == -4.0); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Test Sphere Object", "[features/spheres.feature]") { - Sphere s1; - Sphere s2 = s1; - Sphere s3; - - REQUIRE(s1 == s2); - REQUIRE(s1 != s3); + GIVEN("s1 <- sphere()") + { + Sphere s1; + AND_GIVEN("s2 <- s1") + { + Sphere s2 = s1; + AND_GIVEN("s3 <- sphere()") + { + Sphere s3; + THEN("s1 = s2") + { + REQUIRE(s1 == s2); + } + AND_THEN("s1 != s3") + { + REQUIRE(s1 != s3); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("An intersection encapsulates t and object", "[features/intersections.feature]") { - Sphere s; - Intersection i(3.5, s); + GIVEN("s <- sphere()") + { + Sphere s; + WHEN("intersection(3.5,s)") + { + Intersection i(3.5, s); - REQUIRE(i.distance_t() == 3.5); - REQUIRE(i.object() == s); + THEN("i.t = 3.5") + { + REQUIRE(i.distance_t() == 3.5); + } + AND_THEN("i.object = s") + { + REQUIRE(i.object() == s); + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Aggregating intersections", "[features/intersections.feature]") { - Sphere s; - Intersection i1(1, s); - Intersection i2(2, s); - Intersections xs = Intersections({i1, i2}); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].distance_t() == 1); - REQUIRE(xs[1].distance_t() == 2); + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("i1 <- intersection(1,s)") + { + Intersection i1(1, s); + AND_GIVEN("i2 <- intersection(2,s)") + { + Intersection i2(2, s); + WHEN("xs <- intersections(i1,i2)") + { + Intersections xs = Intersections({i1, i2}); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0].t = 1") + { + REQUIRE(xs[0].distance_t() == 1); + } + AND_THEN("xs[1].t = 2") + { + REQUIRE(xs[1].distance_t() == 2); + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Intersect sets the object on the intersection", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); - Sphere s; - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].object() == s); - REQUIRE(xs[1].object() == s); + GIVEN("r <- ray(point(0, 0, 5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- sphere()") + { + Sphere s; + WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0].object = s") + { + REQUIRE(xs[0].object() == s); + } + AND_THEN("xs[1].object = s") + { + REQUIRE(xs[1].object() == s); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("The hit, when all intersections have positive t", "[features/intersections.feature]") { - Sphere s; - Intersection i1(1, s); - Intersection i2(2, s); - Intersections xs = Intersections({i2, i1}); - - Intersection i = xs.hit(); - - REQUIRE(i == i1); + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("i1 <- intersection(1,s)") + { + Intersection i1(1, s); + AND_GIVEN("i2 <- intersection(2,s)") + { + Intersection i2(2, s); + AND_GIVEN("xs <- intersections(i1,i2)") + { + Intersections xs = Intersections({i2, i1}); + WHEN("i <- hit(xs)") + { + Intersection i = xs.hit(); + THEN("i = i1") + { + REQUIRE(i == i1); + } + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("The hit, when some intersections have negative t", "[features/intersections.feature]") { - Sphere s; - Intersection i1(-1, s); - Intersection i2(1, s); - Intersections xs = Intersections({i2, i1}); - - Intersection i = xs.hit(); - - REQUIRE(i == i2); + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("i1 <- intersection(-1,s)") + { + Intersection i1(-1, s); + AND_GIVEN("i2 <- intersection(2,s)") + { + Intersection i2(1, s); + AND_GIVEN("xs <- intersections(i1,i2)") + { + Intersections xs = Intersections({i2, i1}); + WHEN("i <- hit(xs)") + { + Intersection i = xs.hit(); + THEN("i = i2") + { + REQUIRE(i == i2); + } + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("The hit, when all intersections have negative t", "[features/intersections.feature]") { - Sphere s; - Intersection i1(-2, s); - Intersection i2(-1, s); - Intersections xs = Intersections({i1, i2}); - - auto i = xs.hit(); - - // REQUIRE(i.has_value()); + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("i1 <- intersection(-2,s)") + { + Intersection i1(-2, s); + AND_GIVEN("i2 <- intersection(-1,s)") + { + Intersection i2(-1, s); + AND_GIVEN("xs <- intersections(i1,i2)") + { + Intersections xs = Intersections({i1, i2}); + WHEN("i <- hit(xs)") + { + auto i = xs.hit(); + THEN("i is nothing") + { +#warning TODO + // REQUIRE(i.has_value()); + } + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("The hit is always the lowest nonnegative intersection", "[features/intersections.feature]") { - Sphere s; - Intersection i1(5, s); - Intersection i2(7, s); - Intersection i3(-3, s); - Intersection i4(2, s); - Intersections xs = Intersections({i1, i2, i3, i4}); - - Intersection i = xs.hit(); - - REQUIRE(i == i4); + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("i1 <- intersection(5,s)") + { + Intersection i1(5, s); + AND_GIVEN("i2 <- intersection(7,s)") + { + Intersection i2(7, s); + AND_GIVEN("i3 <- intersection(-3,s)") + { + Intersection i3(-3, s); + AND_GIVEN("i4 <- intersection(2,s)") + { + Intersection i4(2, s); + AND_GIVEN("xs <- intersections(i1, i2, i3, i4)") + { + Intersections xs = Intersections({i1, i2, i3, i4}); + WHEN("i <- hit(xs)") + { + Intersection i = xs.hit(); + THEN("i = i4") + { + REQUIRE(i == i4); + } + } + } + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Translating a ray", "[features/rays.feature]") { - Ray r(Tuple::Point(1, 2, 3), Tuple::Vector(0, 1, 0)); - Matrix m = Matrix::translation(3, 4, 5); - Ray r2 = r.transform(m); - - REQUIRE(r2.origin() == Tuple::Point(4, 6, 8)); - REQUIRE(r2.direction() == Tuple::Vector(0, 1, 0)); + GIVEN("r <- ray(point(1, 2, 3), vector(0, 1, 0))") + { + Ray r(Tuple::Point(1, 2, 3), Tuple::Vector(0, 1, 0)); + AND_GIVEN("m <- translation(3, 4, 5)") + { + Matrix m = Matrix::translation(3, 4, 5); + WHEN("r2 <- transform(r,m)") + { + Ray r2 = r.transform(m); + THEN("r2.origin = point(4, 6, 8)") + { + REQUIRE(r2.origin() == Tuple::Point(4, 6, 8)); + } + AND_THEN("r2.direction = vector(0, 1, 0)") + { + REQUIRE(r2.direction() == Tuple::Vector(0, 1, 0)); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Scaling a ray", "[features/rays.feature]") { - Ray r(Tuple::Point(1, 2, 3), Tuple::Vector(0, 1, 0)); - Matrix m = Matrix::scaling(2, 3, 4); - Ray r2 = r.transform(m); - - REQUIRE(r2.origin() == Tuple::Point(2, 6, 12)); - REQUIRE(r2.direction() == Tuple::Vector(0, 3, 0)); + GIVEN("r <- ray(point(1, 2, 3), vector(0, 1, 0))") + { + Ray r(Tuple::Point(1, 2, 3), Tuple::Vector(0, 1, 0)); + AND_GIVEN("m <- scaling(2, 3, 4)") + { + Matrix m = Matrix::scaling(2, 3, 4); + WHEN("r2 <- transform(r,m)") + { + Ray r2 = r.transform(m); + THEN("r2.origin = point(2, 6, 12)") + { + REQUIRE(r2.origin() == Tuple::Point(2, 6, 12)); + } + AND_THEN("r2.direction = vector(0, 3, 0)") + { + REQUIRE(r2.direction() == Tuple::Vector(0, 3, 0)); + } + } + } + } } /* ------------------------------------------------------------------------- */ @@ -315,34 +539,80 @@ SCENARIO("A sphere's default transformation", "[features/spheres.feature]") SCENARIO("Changing a sphere's transformation", "[features/spheres.feature]") { - Sphere s; - Matrix t = Matrix::translation(2, 3, 4); - s.set_transform(t); - REQUIRE(s.transform() == t); + GIVEN("s <- Sphere()") + { + Sphere s; + AND_GIVEN("t <- translation(2, 3, 4)") + { + Matrix t = Matrix::translation(2, 3, 4); + WHEN("set_transform(s,t)") + { + s.set_transform(t); + THEN("s.transform = t") + { + REQUIRE(s.transform() == t); + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Intersecting a scaled sphere with a ray", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); - Sphere s; - s.set_transform(Matrix::scaling(2, 2, 2)); - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 2); - REQUIRE(xs[0].distance_t() == 3); - REQUIRE(xs[1].distance_t() == 7); + GIVEN("r <- ray(point(0, 0, -5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- Sphere()") + { + Sphere s; + WHEN("set_transform(s,scaling(2,2,2))") + { + s.set_transform(Matrix::scaling(2, 2, 2)); + AND_WHEN("xs <- intersect(s,r)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0].t = 3") + { + REQUIRE(xs[0].distance_t() == 3); + } + AND_THEN("xs[1].t = 7") + { + REQUIRE(xs[1].distance_t() == 7); + } + } + } + } + } } /* ------------------------------------------------------------------------- */ SCENARIO("Intersecting a translated sphere with a ray", "[features/spheres.feature]") { - Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); - Sphere s; - s.set_transform(Matrix::translation(5, 0, 0)); - Intersections xs = s.intersect(r); - - REQUIRE(xs.count() == 0); + GIVEN("r <- ray(point(0, 0, -5), vector(0, 0, 1))") + { + Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); + AND_GIVEN("s <- Sphere()") + { + Sphere s; + WHEN("set_transform(s,translation(5, 0, 0))") + { + s.set_transform(Matrix::translation(5, 0, 0)); + AND_WHEN("xs <- intersect(s,t)") + { + Intersections xs = s.intersect(r); + THEN("xs.count = 0") + { + REQUIRE(xs.count() == 0); + } + } + } + } + } }