Well, our function test code often has a small requirement: When a function in the test code throws an exception, the system automatically displays a debugging window. The debugging window should contain context information for the tester to debug the exception. "By the way, I thought something new. It turned out to be a bit boring breakpoint for Ruby on Rails! ", The readers began to comment with disdain. Well, the old man's words won't go wrong. It is indeed a common breakpoint in ror. But before discussing new things, let's give a brief introduction to the breakpoint of this ox X. For example, the following code:
02: class T3
03: def test_1
04: a = 0
05: 1/a
06: end
07:
08: def test_2
09: p 'test_2'
10: end
11:
12: end
13:
14: t = T3.new
15: begin
16: t.test_1
17: rescue
18: breakpoint
19: end
20: t.test_2
Because test_1 is divided by zero, 18th rows are executed, and the following IRB window is displayed. The pop-up IRB contains the information used when the execution is interrupted, including the current variable, T. We can use local_variables to view variables. We can use source_lines to view the code before and after the interruption. We can even modify test3.rb, load 'test3. rb', and resume execution.
Why do we need to do this in the test code? Haha. Imagine using watir to test a complex network application. Watir cannot find a button on the webpage at Step 1 after 20 minutes. If this IRB window appears, we can view the context of the interrupt and find that the string used to search for the button is incorrect. We changed this string in the test code. After "reload" is changed, the code can be replaced by watir. Then, the IRB window "exit" allows the test code to continue execution. That is to say, code error-interrupted execution-debugging-continue execution. We all know that the efficiency of troubleshooting when an error occurs is much higher than that when the error occurs. No one wants to repeat the first 29 steps. Wait for 20 minutes.
Sounds good, right? However, we are programmers. So the new requirement comes: it would be too late to add begin... rescue breakpoint... end when an error occurs. It would be too troublesome to add all the rows. Can I add no additional code when writing the test code, and just control it in one place? For example, the code above is changed to the following:
02: class T3
03: def test_1
04: a = 0 05: 1/a
06: end 07:
08: def test_2
09: p 'test_2' 10: end 11:
12: monitor /test/ 13: end 14:
15: t = T3.new
16: t.test_1
17: t.test_2
Pay attention to the 12th rows. We add a new function. The breakpoint IRB window is automatically displayed when any function whose name matches/test/fails.
This is very convenient. Of course, we also allow more fine-grained syntaxes such as monitor: test_1. In this way, we do not need to add more code, but can also control
When can breakpoint take effect? (for example, when a global configuration is disabled, let the monitor do nothing ). Well, the elders of AOP laugh.
. The old guys who are familiar with lisp macro also laughed. Let's see how ruby is implemented. It is also very simple. Below is a piece of basic code. I removed
Many irrelevant details.We open the built-in class module and add a key instance method, monitor. This function, monitor, uses the function passed to it as begin... rescue... breakpoint... end
Package. Therefore, our function automatically has the breakpoint function. It's so simple.
Require'Breakpoint'
ClassModule
DefMatch? (Element, array)
Array. EachDo| E |
E = E. to_sIfE. instance_of? (Symbol)
Return True IfElement.Match(E)
End
Return False End
Def Monitored_method_ids(* Method_names)
Return Self.Instance_methods(False).Inject([])Do| Result, method |
Result.Push(Method. to_sym)IfMatch? (Method, method_names)
Result
End
End
Def Monitor(* ARGs)
Monitored_method_ids(* ARGs). EachDo| Method |
Module_eval <-eval_end
Alias_method :__#{Method. to_ I }__, :#{ method. to_s}
Def #{Method. to_s}
Begin
__#{Method. to_ I }__
Rescue=> E
Breakpoint
End
End
Eval_end
End
End
End
Questions:
- What should I do if I want to implement the above monitor into the class of the test code? Tip: class <self
- What are the major defects of the above Code? Tip: for example, what information is incorrect? What existing functions are damaged?
- How to fix those defects? Tip: breakpoint. Rb
- What if we want to add the breakpoint function to each row of a function? Tip: lossless syntax tree