### Question:
DebugOperationTracer implements OperationTracer { @Override public void traceExecution(final MessageFrame frame, final ExecuteOperation executeOperation) { final Operation currentOperation = frame.getCurrentOperation(); final int depth = frame.getMessageStackDepth(); final String opcode = currentOperation.getName(); final int pc = frame.getPC(); final Gas gasRemaining = frame.getRemainingGas(); final Bytes inputData = frame.getInputData(); final Optional<Bytes32[]> stack = captureStack(frame); final WorldUpdater worldUpdater = frame.getWorldState(); final Optional<Bytes32[]> stackPostExecution; final OperationResult operationResult = executeOperation.execute(); final Bytes outputData = frame.getOutputData(); final Optional<Bytes[]> memory = captureMemory(frame); stackPostExecution = captureStack(frame); if (lastFrame != null) { lastFrame.setGasRemainingPostExecution(gasRemaining); } final Optional<Map<UInt256, UInt256>> storage = captureStorage(frame); final Optional<Map<Address, Wei>> maybeRefunds = frame.getRefunds().isEmpty() ? Optional.empty() : Optional.of(frame.getRefunds()); lastFrame = new TraceFrame( pc, Optional.of(opcode), gasRemaining, operationResult.getGasCost(), frame.getGasRefund(), depth, operationResult.getHaltReason(), frame.getRecipientAddress(), frame.getApparentValue(), inputData, outputData, stack, memory, storage, worldUpdater, frame.getRevertReason(), maybeRefunds, Optional.ofNullable(frame.getMessageFrameStack().peek()).map(MessageFrame::getCode), frame.getCurrentOperation().getStackItemsProduced(), stackPostExecution, currentOperation.isVirtualOperation(), frame.getMaybeUpdatedMemory(), frame.getMaybeUpdatedStorage()); traceFrames.add(lastFrame); frame.reset(); } DebugOperationTracer(final TraceOptions options); @Override void traceExecution(final MessageFrame frame, final ExecuteOperation executeOperation); @Override void tracePrecompileCall(
      final MessageFrame frame, final Gas gasRequirement, final Bytes output); @Override void traceAccountCreationResult(
      final MessageFrame frame, final Optional<ExceptionalHaltReason> haltReason); List<TraceFrame> getTraceFrames(); void reset(); List<TraceFrame> copyTraceFrames();  }### Answer:
@Test public void shouldCaptureFrameWhenExceptionalHaltOccurs() { final MessageFrame frame = validMessageFrame(); final Map<UInt256, UInt256> updatedStorage = setupStorageForCapture(frame); final DebugOperationTracer tracer = new DebugOperationTracer(new TraceOptions(true, true, true)); tracer.traceExecution( frame, () -> new OperationResult( Optional.of(Gas.of(50)), Optional.of(ExceptionalHaltReason.INSUFFICIENT_GAS))); final TraceFrame traceFrame = getOnlyTraceFrame(tracer); assertThat(traceFrame.getExceptionalHaltReason()) .contains(ExceptionalHaltReason.INSUFFICIENT_GAS); assertThat(traceFrame.getStorage()).contains(updatedStorage); }