This commit is contained in:
Kacper Marzecki 2025-06-19 13:17:18 +02:00
parent 646afaad64
commit cb8dddc326
2 changed files with 144 additions and 0 deletions

View File

@ -57438,3 +57438,141 @@ defmodule TupleTestHelpers do
> Tokens: 25k sent, 457 received. Cost: $0.04 message, $0.08 session.
> Applied edit to test.exs
#### /clear
#### /ask I've got a problem with debugging this thing. In some test cases I need to access a detailed trace of whats going on. Most of the time I don't care, because they pass. We need to add detailed logs which i can enable only for a select test case via a Process switch. Lets design it
#### I've got a problem with debugging this thing. In some test cases I need to access a detailed trace of whats going on. Most of the time I don't care, because they pass. We need to add detailed logs which i can enable only for a select test case via a Process switch. Lets design it
Okay, let's design a conditional logging mechanism for detailed tracing.
**Design Proposal: Conditional Debug Tracing**
We'll introduce a tracing facility within the existing `Tdd.Debug` module. This facility will be controlled by a flag in the process dictionary, allowing tests to enable detailed logging on demand.
**1. Control Mechanism (in `Tdd.Debug` module):**
* **Process Flag:** A key, for example, `@trace_flag :tdd_debug_trace_enabled`, will be used with `Process.put/2` and `Process.get/2`.
* **Control Functions:**
* `enable_trace/0`: Sets the process flag to `true`.
```elixir
# In Tdd.Debug
@trace_flag :tdd_debug_trace_enabled
def enable_trace, do: Process.put(@trace_flag, true)
```
* `disable_trace/0`: Sets the process flag to `false` (or removes it).
```elixir
# In Tdd.Debug
def disable_trace, do: Process.put(@trace_flag, false)
```
* `trace_enabled?/0`: Checks the state of the flag. This can be private if only used by the macros.
```elixir
# In Tdd.Debug
defp trace_enabled?, do: Process.get(@trace_flag, false) == true
```
**2. Logging Macros (in `Tdd.Debug` module):**
To ensure that potentially expensive operations (like data inspection or string formatting) are only performed when tracing is active, the macros will accept zero-arity functions that produce the content to be logged.
* `dlog_msg(message_producer_fun)`: For logging simple string messages.
* `message_producer_fun`: A `fn -> "message string" end`.
* *Behavior*: If tracing is enabled, it executes `message_producer_fun.()` and prints the result using `IO.puts/1`.
```elixir
# In Tdd.Debug
defmacro dlog_msg(message_producer_fun) do
quote do
if Tdd.Debug.trace_enabled?() do
IO.puts(unquote(message_producer_fun).())
end
end
end
```
* `dlog(label, data_producer_fun)`: For inspecting data with a label.
* `label`: An atom or string for `IO.inspect/2`.
* `data_producer_fun`: A `fn -> data_to_inspect end`.
* *Behavior*: If tracing is enabled, it executes `data_producer_fun.()` and inspects the result using `IO.inspect(result, label: label)`.
```elixir
# In Tdd.Debug
defmacro dlog(label, data_producer_fun) do
quote do
if Tdd.Debug.trace_enabled?() do
IO.inspect(unquote(data_producer_fun).(), label: unquote(label))
end
end
end
```
* `dlog_action(action_producer_fun)`: For executing an action (like calling `Tdd.Debug.print/1`) only when tracing is enabled.
* `action_producer_fun`: A `fn -> perform_io_action() end`.
* *Behavior*: If tracing is enabled, it executes `action_producer_fun.()`.
```elixir
# In Tdd.Debug
defmacro dlog_action(action_producer_fun) do
quote do
if Tdd.Debug.trace_enabled?() do
unquote(action_producer_fun).()
:ok # Ensure the macro expression has a consistent return value
end
end
end
```
**3. Usage Example:**
* **In a specific test case:**
```elixir
defmodule MyProblematicTest do
use ExUnit.Case
alias Tdd.Debug
setup do
Debug.enable_trace()
on_exit(fn -> Debug.disable_trace() end) # Ensure cleanup
:ok
end
test "scenario requiring detailed trace" do
# ... test code that calls into TDD modules ...
assert true # placeholder
end
end
```
* **In core logic (e.g., `Tdd.Compiler.loop_until_stable/3`):**
The existing `IO.puts` and `IO.inspect` calls can be converted.
```elixir
# In Tdd.Compiler, after aliasing or requiring Tdd.Debug
# alias Tdd.Debug
defp loop_until_stable(prev_id, step_function, iteration \\ 0) do
Debug.dlog_msg(fn -> "\n--- Fixed-Point Iteration: #{iteration} ---" end)
Debug.dlog("prev_id", fn -> prev_id end)
Debug.dlog_action(fn -> Tdd.Debug.print(prev_id) end) # For detailed graph view
raw_next_id = step_function.(prev_id)
Debug.dlog("raw_next_id (after step_function)", fn -> raw_next_id end)
Debug.dlog_action(fn -> Tdd.Debug.print(raw_next_id) end)
next_id = Algo.simplify(raw_next_id)
Debug.dlog("next_id (after simplify)", fn -> next_id end)
Debug.dlog_action(fn -> Tdd.Debug.print(next_id) end)
if next_id == prev_id do
Debug.dlog_msg(fn -> "--- Fixed-Point Reached! ---" end)
next_id
else
# ... existing safety break and recursive call ...
if iteration > 2 do # Example existing condition
# ...
end
loop_until_stable(next_id, step_function, iteration + 1)
end
end
```
This design provides a flexible way to get detailed traces for specific scenarios without affecting the performance or output of regular test runs. The use of functions ensures lazy evaluation of potentially costly debug message formatting.
> Tokens: 32k sent, 1.3k received. Cost: $0.05 message, $0.12 session.

View File

@ -4185,3 +4185,9 @@
# 2025-06-16 11:51:48.065221
+n
# 2025-06-19 10:22:37.019564
+/clear
# 2025-06-19 10:25:14.825350
+/ask I've got a problem with debugging this thing. In some test cases I need to access a detailed trace of whats going on. Most of the time I don't care, because they pass. We need to add detailed logs which i can enable only for a select test case via a Process switch. Lets design it