[hemmerling] Tcl / Tk ( tickle ) 2/2 - Debugging & Testing

Related page:

Static Code Analysis with Tcl / Tk

Style Guides

Ray Johnson's Style Guide Rules

5.2 Basic Syntax Rules

Below are some specific rules governing the syntax of names. Please follow the rules exactly, since they make it possible to determine certain properties of a variable just from its name.

  1. Exported names for both procedures and variables always start with a lower-case letter. Procedures and variables that are meant only for use with in the current package or namespace should start with an upper-case letter. We chose lower-case for the exported symbols because it is possible they may be commonly used from the command line and they should be easy to write. For example:
    # CountNum is a private variable
    set CountNum 0
    # The function addWindow is public
    proc addWindow {} {...
    # newWindow is a public interface in the spectcl namespace
    proc spectcl::newWindow {} {...
  2. In multi-word names, the first letter of each trailing word is capitalized. Do not use underscores or dashes as separators between the words of a name.
    set numWindows 0
  3. Any variable whose value refers to another variable has a name that ends in Name. Furthermore, the name should also indicate what type of variable the name is referring to. These names are often used in arguments to procedures that are taking a name of a variable.
    proc foo::Bar {arrayName} {
        upvar 1 $arrayName array
        ...
    } 
  4. Variables that hold Tcl code that will be evaled should have names ending in Script.
    proc log::eval {logScript} {
        if {$Log::logOn} {
            set result [catch {eval $logScript} msg]
            ... 
  5. Variables that hold a partial Tcl command that must have additional arguments appended

before being a valid script should have names ending in Cmd.

foreach scrollCmd $listScrollCmds {
    eval $scrollCmd $args
}

6. Low-level coding Conventions

This section describes several low-level syntactic rules for writing Tcl code. These rules help to ensure that all of the Tcl code looks the same, and they prohibit a few confusing coding constructs.

6.1 Indents are 4 Spaces

Each level of indentation should be four spaces. There are ways to set 4-space indents in all of the most common editors. Be sure that your editor really uses four spaces for the indent, rather than just displaying tabs as four spaces wide; if you use the latter approach then the indents will appear eight spaces wide in other editors.

6.2 Code Comments occupy full Lines

Comments that document code should occupy full lines, rather than being tacked onto the ends of lines containing code. The reason for this is that side-by-side comments are hard to see, particularly if neighboring statements are long enough to overlap the side-by-side comments. Also it is easy to place comments in a place that could cause errors. Comments must have exactly the structure shown in Figure 3, with a blank line above and below the comment. The leading blank line can be omitted if the comment is at the beginning of a block, as is the case in the second comment in Figure 3. Each comment should be indented to the same level as the surrounding code. Use proper English in comments: write complete sentences, capitalize the first word of each sentence, and so on.

# If we are running on the Macintosh platform then we can
# assume that the sources are located in the resource fork
# of our application, and we do not need to search for them.
if {$tcl_platform(platform) == “macintosh”} {
    return
}
foreach dir $dirList {
    # If the source succeds then we are done.
    if {![catch {source [file join $dir file.tcl]}]} {
        break
    }
}

Figure 3. Comments in code have the form shown above, using full lines, with lined-up hash marks, the comment takes at least a full line, and blank separator lines around each comment (except that the leading blank line can be omitted if the comment is at the beginning of a code block).

6.3 Continuation Lines are indented 8 Spaces

You should use continuation lines to make sure that no single line exceeds 80 characters in length. Continuation lines should be indented 8 spaces so that they won’t be confused with an immediately-following nested block. Pick clean places to break your lines for continuation, so that the continuation doesn’t obscure the structure of the statement. For example, if a procedure call requires continuation lines, try to avoid situations where a single argument spans multiple lines. If the test for an if or while command spans lines, try to make each line have the same nesting level of parentheses and/or brackets if possible. I try to start each continuation line with an operator such as *, &&, or ||; this makes it clear that the line is a continuation, since a new statement would never start with such an operator.

6.4 Only one Command per Line

You should only have one Tcl command per line on the page. Do not use the semi-colon character to place multiple commands on the same line. This makes the code easier to read and helps with debugging.

6.5 Curly Braces: { goes at the end of a Line

Open curly braces can not appear on lines by themselves in Tcl. Instead, they should be placed at the end of the preceding line. Close curly braces are indented to the same level as the outer code, i.e., four spaces less than the statements they enclose. However, you should always use curly braces rather than some other list generating mechanism that will work in the Tcl language. This will help make code more readable, will avoid unwanted side effects, and in many cases will generate faster code with the Tcl compiler. Control structures should always use curly braces, even if there is only one statement in the block. Thus you shouldn’t write code like

if {$tcl_platform(platform) == "unix"} return

but rather

if {$tcl_platform(platform) == "unix"} {
    return
}

This approach makes code less dense, but it avoids potential mistakes like unwanted Tcl substitutions. It also makes it easier to set breakpoints in a debugger, since it guarantees that each statement is on a separate line and can be named individually.

6.6 Parenthesize Expressions

Use parentheses around each subexpression in an expression to make it absolutely clear what is the evaluation order of the expression (a reader of your code should not need to remember Tcl’s precedence rules). For example, don’t type

if {$x > 22 && $y <= 47} ...

Instead, type this:

if {($x > 22) && ($y <= 47)} ...
6.7 Always use the return statement

You should always explicitly use the return statement to return values from a Tcl procedure. By default Tcl will return the value of the last Tcl statement executed in a Tcl procedure as the return value of the procedure which often leads to confusion as to where the result is coming from. In addition, you should use a return statement with no argument for procedures whose results are ignored. Supplying this return will actually speed up your application with the new Tcl compiler. For example, don’t write code like this:

proc foo {x y} {
    if {$x < 0} {
        incr x
    } else {
        expr $x + $y
    }
}

But rather, type this:

proc foo {x y} {
    if {$x < 0} {
        return [incr x]
    } else {
        return [expr $x + $y]
    }
}

For Tcl procedures that have no return value a single return statement with no arguments is placed at the end of the procedure.

6.8 Switch statements

The switch statement should be formatted as below. Always use the – option to avoid having the string be confused with an option. This can happen when the string is user generated. Comments can be added on the same line as the pattern to comment the pattern case. The comments for each case should line up on the same tab stop and must be within the braces. Note that this is an exception to the standard commenting conventions.

switch -regexp -- $string {
    plus -
    add { # Do add task
    ...
    }
    subtract { # Do subtract case
    ...
    }
    default {
    ...
    }
}
6.9 If statements

Never use the then word of an if statement. It is syntactic sugar that really isn’t that useful. However, the else word should always be used as it does impart some semantic information and it is more like the C language. Here is an example:

if {$x < 0} {
    ...
} elseif {$x == 0} {
    ...
} else {
    ...
}

Tools

Resources

Interactive Development & Debugging

By built-in Commands ( "All Batteries included" ) & no or little extra Code

By Tools

By Overwriting / Overloading

With TclCon

With Wish

demo.tcl

bind all <Shift-F1> {console show}
set LabelText "Hello"
set Message "Hello World!"
pack [button .b -text $LabelText -command onButtonClick]
proc onButtonClick {} {
puts "Start of Reaction to Buttonclick" 
    tk_messageBox -parent . -message $::Message
puts "End of Reaction to Buttonclick"
}

console_logging.txt

% info vars
tcl_rcFileName tcl_version argv0 argv tcl_interactive tk_library tk_version LabelText auto_path errorCode tk_strictMotif errorInfo auto_index env tcl_patchLevel Message argc tk_patchLevel tcl_library tcl_platform% 
% winfo ch .
.b

# Replacement of the message of a modal window
% set Message
Hallo World!
% set Message "Hello Tcl User!"
Hello Tcl User!
# Now press the Button "Hello" 
# and see that the new message
# is displayed on the button of
# the modal window

# Replacement on the callback function
# for a buttonclick:
% proc onButtonClick {} {
puts "New Start of Reaction to Buttonclick"
     tk_messageBox -parent . -message $::Message
puts "New End of Reaction to Buttonclick"
}
# Now press the Button "Hello" 
# and see that by the buttonclick
# now new messages are displayed 
# in the console window

% proc e {} {uplevel #0 [clipboard get]}
# Now mark the Tcl command "winfo ch .", 
# copy it with CTRL-C to the keyboard
# and execute the command "e"
# By this, the contents of the clipboard 
# is executed as Tcl command
% e
.b

% proc i {} {puts $::errorInfo}
# Now cause an error by an invalid command
% abc
invalid command name "abc"
# So you can replay the last error, 
# by calling the "i" procedure 
% i
invalid command name "abc"
while executing
"abc"

Instructions

  1. Execute the “Wish” GUI application.
  2. Load and execute the “demo.tcl” application by “File / Source “demo.tcl”. This starts
    1. The GUI application “wish”, a window sith a “Hello” button.
    2. The console window “Console”.
  3. Switch the window context of the “wish” application, and press “SHIFT-F1”. This (re-)opens the console window “Console”. If you close the console window, you can reopen it by this again at every time.
  4. Load “console_logging.txt” in an editor, e.g. in the Eclipse IDE. On Windows, you may mark and copy code instructions from the editor window by “CTRL-C” and paste it by “CTRL-V” in the “wish” window so that it is accepted as input as if typed in by keyboard.
  5. Check how you can explore the Tcl environment by
    1. “info vars”.
    2. “winfo .b”.
  6. Press the button “Hello”, and press the button “Hello World!” of the upcoming modal window. Take notice of the messages in the console window.
  7. In the console window, set a new message by executing the ' set Message “Hello Tcl User!”' command.
  8. Press the button “Hello”, and you see that the upcoming modal window now has a button “Hello Tcl User!”. Press this button.
  9. In the console window, execute a command to redefine the “onButtonClick {}” procedure.
  10. Press the button “Hello”, and you see that the messages in the console window are different.
  11. By “e {} {uplevel #0 [clipboard get]}”, you may execute the contents of the clipboard as Tcl command. Example:
    1. Mark the Tcl command “winfo ch .”.
    2. Copy it with CTRL-C to the keyboard.
    3. Execute the command “e” at Tclsh. By this, the contents of the clipboard is executed as Tcl command.
  12. By “proc i {} {puts $::errorInfo}” you may recall the Tcl variable “errorInfo” which contains the last error message. Example:
    1. Execute the unknown Tcl command “abc” at Tclsh.
    2. Display the last Tcl error message, by executing “i”.

Resources

Unit Testing

tcltest

The Simple Development Library

t-unit

tclunit

TclUnit

Application Testing with Expect, DejaGnu, tcl-automated-test-framework

Expert

Tools based on Expert

Appropriate OpenDirectory Directory Pages

 
en/tickle02.html.txt · Last modified: 2017/08/21 22:25 (external edit) · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki