diff --git a/optimization/optimizers/line_search/bracket.h b/optimization/optimizers/line_search/bracket.h
index 348d376a44524dada0e36bc8d6584b7ee7b1372a..fb9e1a089f69aee65a610394f347939d422ba335 100644
--- a/optimization/optimizers/line_search/bracket.h
+++ b/optimization/optimizers/line_search/bracket.h
@@ -7,10 +7,18 @@
 namespace optimization {
 
 //--------------------------------------------------------------------------------------------------
-// TODO: This class should guarantee y_1_ > y_2_ < y_3_ and x_1_ < x_2_ < x_3_ or x_1_ > x_2_ > x_3_
-// (with the "or" evaluted before the "and").
+// TODO: Could be nice for this class to guarantee y_1_ > y_2_ < y_3_ and x_1_ < x_2_ < x_3_ or
+// x_1_ > x_2_ > x_3_ (with the "or" evaluted before the "and"). But for now this feels like
+// egregious overengineering.
 class Bracket {
 public:
+    Bracket() {}
+    Bracket(Scalar x_1, Scalar x_2, Scalar x_3, Scalar y_1, Scalar y_2, Scalar y_3)
+        : x_1_(x_1), x_2_(x_2), x_3_(x_3), y_1_(y_1), y_2_(y_2), y_3_(y_3)
+    {}
+    Bracket(Bracket const&) = default;
+    Bracket& operator=(Bracket const&) = default;
+
     Scalar x_1() const { return x_1_; }
     Scalar x_2() const { return x_2_; }
     Scalar x_3() const { return x_3_; }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5d2704d5a8545ed1937f88606ab3408c9ede8342..a186b4e3ab1889131fa97279a9c902f70e2a15c4 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_executable(test
     main.cpp
     optimizers/line_search/bracket.cpp
+    optimizers/line_search/golden_section.cpp
 )
 target_link_libraries(test optimization_lib catch2)
diff --git a/test/optimizers/line_search/bracket.cpp b/test/optimizers/line_search/bracket.cpp
index 097c75435edf5e58f4def3fe20887cae74d74339..b2dd1ae4604a507eef79374dbbc0b7205b1e5776 100644
--- a/test/optimizers/line_search/bracket.cpp
+++ b/test/optimizers/line_search/bracket.cpp
@@ -4,7 +4,7 @@
 using namespace optimization;
 
 //--------------------------------------------------------------------------------------------------
-TEST_CASE("Bracket", "[bracket]") {
+TEST_CASE("Bracket", "[Bracket]") {
     BracketFinder bracket;
 
     SECTION("parabola") {
diff --git a/test/optimizers/line_search/golden_section.cpp b/test/optimizers/line_search/golden_section.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..875c65923cf5d32407eda3f61afa5fcaf46ed942
--- /dev/null
+++ b/test/optimizers/line_search/golden_section.cpp
@@ -0,0 +1,36 @@
+#include "catch.hpp"
+#include "optimizers/line_search/golden_section.h"
+
+using namespace optimization;
+
+//--------------------------------------------------------------------------------------------------
+TEST_CASE("GoldenSection", "[GoldenSection]") {
+    // The 1e-8 sets the absolute tolerance on the width of the bracket.
+    // There's still a default relative tolerance in effect as well, but these tests don't hit it.
+    GoldenSection golden_section(1e-8);
+    Bracket bracket;
+    Sample<Scalar> result;
+
+    SECTION("parabola") {
+        struct Parabola {
+            void eval(Scalar x, Scalar& y) const { y = x * x; }
+        };
+        Parabola parabola;
+
+        bracket = Bracket(-2, -1, 2, 4, 1, 4);
+        result = golden_section.optimize(parabola, bracket);
+        // The parabola is flat here so y accuracy had better exceed x accuracy.
+        REQUIRE(std::abs(result.point) < 1e-8);
+        REQUIRE(std::abs(result.value) < 1e-16);
+        // Just a sanity check.
+        REQUIRE(golden_section.n_evaluations() < 100);
+
+        bracket = Bracket(50, 10, -100, 2500, 100, 10000);
+        result = golden_section.optimize(parabola, bracket);
+        // The parabola is flat here so y accuracy had better exceed x accuracy.
+        REQUIRE(std::abs(result.point) < 1e-8);
+        REQUIRE(std::abs(result.value) < 1e-16);
+        // Just a sanity check.
+        REQUIRE(golden_section.n_evaluations() < 100);
+    }
+}