[Style] testing, comments, some reorg; Vincent's comments
This commit is contained in:
parent
b99f7151a2
commit
4bf1a63d56
|
@ -30,7 +30,9 @@ act in this context.
|
||||||
Write meaningful commit messages. The first line (say 80 chars) should
|
Write meaningful commit messages. The first line (say 80 chars) should
|
||||||
provide a concise summary of the commit. If the message must be longer,
|
provide a concise summary of the commit. If the message must be longer,
|
||||||
edit the rest of the message in your text editor and leave a blank line
|
edit the rest of the message in your text editor and leave a blank line
|
||||||
between the summary line and the rest of the message.
|
between the summary line and the rest of the message. The message for bug
|
||||||
|
report fixes should contain ``Close PR NNNNN'' so that bug reports are
|
||||||
|
automatically closed.
|
||||||
|
|
||||||
To avoid 'merge commits', update your repository with @tt{git --rebase pull}.
|
To avoid 'merge commits', update your repository with @tt{git --rebase pull}.
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,35 @@ Seasoned Schemers, not necessarily Racketeers, also use triple and
|
||||||
quadruple semicolons. This is considered a courtesy to distinguish file
|
quadruple semicolons. This is considered a courtesy to distinguish file
|
||||||
headers from section headers.
|
headers from section headers.
|
||||||
|
|
||||||
|
In addition to ``;'', we have two other mechanisms for commenting code:
|
||||||
|
``#|...|#'' for blocks and ``#;'' to comment out an expression.
|
||||||
|
|
||||||
|
In rare cases there might be a more substantial piece of text or code, and
|
||||||
|
in that case the block comment style can be more convenient than
|
||||||
|
semicolons. Another use of block comments is for code samples to be
|
||||||
|
copied and pasted into a file. Either way, block comments are not used
|
||||||
|
for single-line comments.
|
||||||
|
|
||||||
|
Expression comments---``#;''---apply to the following S-expression. This
|
||||||
|
makes them a useful tool for debugging. They can even be composed in
|
||||||
|
interesting ways with other comments, for example, ``#;#;'' will comment
|
||||||
|
two expressions, and a line with just ``;#;'' gives you a single-character
|
||||||
|
``toggle'' for the expression that starts on the next line. But on the
|
||||||
|
flip side, lots tools don't process them properly---treating them instead
|
||||||
|
as a ``#'' followed by a commented line. For example, in DrRacket
|
||||||
|
S-expression comments are ignored when it comes to syntax coloring, which
|
||||||
|
makes it easy to miss them. In Emacs, the commented text is colored like a
|
||||||
|
comment and treated as text, which makes it difficult to edit as code.
|
||||||
|
The bottom line here is that ``#;'' comments are useful for debugging, but
|
||||||
|
try to avoid leaving them in committed code. If you really want to use
|
||||||
|
``#;'', clarify their use with a line comment (``;'').
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
@section{Definitions}
|
@section{Definitions}
|
||||||
|
|
||||||
Racket comes with quite a few definitional constructs, including
|
Racket comes with quite a few definitional constructs, including
|
||||||
@scheme[let], @scheme[let*], @scheme[letrec], and @scheme[define]. Except
|
@scheme[let], @scheme[let*], @scheme[letrec], and @scheme[define]. Except
|
||||||
for the last one, definitional construct increase the indentation level.
|
for the last one, definitional constructs increase the indentation level.
|
||||||
Therefore, favor @scheme[define] when feasible.
|
Therefore, favor @scheme[define] when feasible.
|
||||||
|
|
||||||
@compare[
|
@compare[
|
||||||
|
@ -90,11 +113,12 @@ prefer them over @scheme[if].
|
||||||
racket
|
racket
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
[(empty? l) true]
|
[(empty? l) #false]
|
||||||
[else
|
[else
|
||||||
(define f (fir l))
|
(define f (fir l))
|
||||||
(define r (rest l))
|
(define r (rest l))
|
||||||
(and (flat-rate f)
|
(if (discounted? f)
|
||||||
|
(discount-rate f)
|
||||||
(curved f (chk r)))])
|
(curved f (chk r)))])
|
||||||
]
|
]
|
||||||
@racketmod[#:file
|
@racketmod[#:file
|
||||||
|
@ -102,10 +126,11 @@ racket
|
||||||
racket
|
racket
|
||||||
|
|
||||||
(if (empty? l)
|
(if (empty? l)
|
||||||
true
|
#false
|
||||||
(let ([f (fir l)]
|
(let ([f (fir l)]
|
||||||
[r (rest l)])
|
[r (rest l)])
|
||||||
(and (flat-rate f)
|
(if (discounted? f)
|
||||||
|
(discount-rate f)
|
||||||
(curved f (chk r)))))
|
(curved f (chk r)))))
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -198,7 +223,7 @@ Even a curried function does not need @racket[lambda].
|
||||||
@tt{good}
|
@tt{good}
|
||||||
racket
|
racket
|
||||||
|
|
||||||
(define ((staged-image-composition fixed-image) variable-image)
|
(define ((cut fx-image) image2)
|
||||||
...)
|
...)
|
||||||
]
|
]
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
|
@ -206,8 +231,8 @@ racket
|
||||||
@tt{acceptable}
|
@tt{acceptable}
|
||||||
racket
|
racket
|
||||||
|
|
||||||
(define (staged-image-composition fixed-image)
|
(define (cut fx-image)
|
||||||
(lambda (variable-image)
|
(lambda (image2)
|
||||||
...))
|
...))
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -233,7 +258,7 @@ The identity function is @racket[values]:
|
||||||
@section{Traversals}
|
@section{Traversals}
|
||||||
|
|
||||||
With the availability of @racket[for/fold], @racket[for/list],
|
With the availability of @racket[for/fold], @racket[for/list],
|
||||||
@racket[for/vector], and friends, programming with for @racket[for] loops
|
@racket[for/vector], and friends, programming with @racket[for] loops
|
||||||
has become just as functional as programming with @racket[map] and
|
has become just as functional as programming with @racket[map] and
|
||||||
@racket[foldr]. With @racket[for*] loops, filter, and termination clauses
|
@racket[foldr]. With @racket[for*] loops, filter, and termination clauses
|
||||||
in the iteration specification, these loops are also far more concise than
|
in the iteration specification, these loops are also far more concise than
|
||||||
|
@ -270,8 +295,11 @@ racket
|
||||||
racket
|
racket
|
||||||
|
|
||||||
;; [Listof X] -> Number
|
;; [Listof X] -> Number
|
||||||
(define (sum-up s)
|
(define (sum-up alist)
|
||||||
(foldr (lambda (x sum) (+ sum x)) 0 s))
|
(foldr (lambda (x sum)
|
||||||
|
(+ sum x))
|
||||||
|
0
|
||||||
|
alist))
|
||||||
|
|
||||||
;; example:
|
;; example:
|
||||||
(sum-up '(1 2 3))
|
(sum-up '(1 2 3))
|
||||||
|
|
|
@ -23,7 +23,7 @@ This section explains these three points as far as the Racket code base is
|
||||||
code base.
|
code base.
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
@section[#:tag "correctness"]{Correctness}
|
@section[#:tag "correctness"]{Correctness and Testing}
|
||||||
|
|
||||||
@nested[#:style 'inset]{@italic{I have bug reports, therefore I exist.} -- Matthias,
|
@nested[#:style 'inset]{@italic{I have bug reports, therefore I exist.} -- Matthias,
|
||||||
watching Matthew, Robby, Shriram and others create the original code base}
|
watching Matthew, Robby, Shriram and others create the original code base}
|
||||||
|
@ -45,54 +45,8 @@ We ensure this basic level of correctness with large test suites. Our test
|
||||||
DrRacket comes with an automatic GUI player that explores its
|
DrRacket comes with an automatic GUI player that explores its
|
||||||
functionality.
|
functionality.
|
||||||
|
|
||||||
Most tests suites live in @tt{collects/tests/} in the PLT
|
For details on testing in the context of the Racket code base, see
|
||||||
repository. @margin-note*{Due to historical reasons, a few collections
|
@secref{testing}.
|
||||||
come with their own local test suites.} These test suites suggest a
|
|
||||||
culture of testing per tool or language. If you add a new collection,
|
|
||||||
create a new test suite in the @tt{tests} collection.
|
|
||||||
|
|
||||||
Run the test suites before you commit. After you commit, watch for and
|
|
||||||
read(!) @hyperlink["http://drdr.racket-lang.org/"]{DrDr}'s emails. Do
|
|
||||||
@emph{not} ignore them. If you have a tests that regularly fails, consider
|
|
||||||
splitting your test directory into two parts: @tt{success} and
|
|
||||||
@tt{failure}. The former is for tests that should succeed now, and the
|
|
||||||
latter is for tests that are currently intended to fail. See the
|
|
||||||
@hyperlink["https://github.com/plt/racket/tree/master/collects/tests/typed-scheme"]{Typed
|
|
||||||
Racket testing arrangement} for an example.
|
|
||||||
|
|
||||||
When you debug an existing piece of code, formulate a test case first. Put
|
|
||||||
it into the test suite for the component so the mistake will never be
|
|
||||||
accidentally re-introduced and add a note that points to the problem
|
|
||||||
report. Second, modify the code to fix the mistake. Do this second to be
|
|
||||||
sure you didn't introduce a mistake in your tests; it is all too easy to
|
|
||||||
think you have fixed a mistake when in reality your new test just doesn't
|
|
||||||
properly reveal the old mistake. Third, re-run the test suite to ensure
|
|
||||||
that the mistake is fixed and no existing tests fail.
|
|
||||||
|
|
||||||
If there is no test suite and you aren't sure how to build one, then ask on
|
|
||||||
the developer mailing list. Perhaps people will explain why there isn't
|
|
||||||
one or they will sketch how to create one. Please don't ignore the
|
|
||||||
problem. If you cannot build a test suite, you have a few options:
|
|
||||||
|
|
||||||
@itemlist[#:style 'ordered
|
|
||||||
|
|
||||||
@item{Add functionality to the library to enable testing. Of course,
|
|
||||||
adding functionality means adding external documentation. Robby and
|
|
||||||
Matthew have done so for the GUI library, and there is now a large
|
|
||||||
automated test suite for DrRacket. So even GUI programs can come with
|
|
||||||
extended test suites.}
|
|
||||||
|
|
||||||
@item{Add an end-to-end test that may have to be verified by a human.
|
|
||||||
For example, it might be hard to test Slideshow, so you could create a
|
|
||||||
slide set and describe what it should look like so future maintainers to
|
|
||||||
verify when @emph{they} make changes. Consider this the @emph{last and
|
|
||||||
least desirable} option, however.}
|
|
||||||
]
|
|
||||||
@;
|
|
||||||
The lack of tests for some collection will not disappear overnight. But if
|
|
||||||
we all contribute a little bit, we will eventually expand the test suites
|
|
||||||
to cover the entire code base, and future generations of maintainers will
|
|
||||||
be grateful.
|
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
@section{Maintenance}
|
@section{Maintenance}
|
||||||
|
|
|
@ -56,10 +56,11 @@ Also, look over the commit messages. If you see problems with the code
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
@include-section{correct-maintain-speed.scrbl}
|
@include-section{correct-maintain-speed.scrbl}
|
||||||
@include-section{some-performance.scrbl}
|
@include-section{testing.scrbl}
|
||||||
@include-section{unit.scrbl}
|
@include-section{unit.scrbl}
|
||||||
@include-section{constructs.scrbl}
|
@include-section{constructs.scrbl}
|
||||||
@include-section{textual.scrbl}
|
@include-section{textual.scrbl}
|
||||||
|
@include-section{some-performance.scrbl}
|
||||||
@include-section{branch-and-commit.scrbl}
|
@include-section{branch-and-commit.scrbl}
|
||||||
@include-section{acknowledgment.scrbl}
|
@include-section{acknowledgment.scrbl}
|
||||||
|
|
||||||
|
|
71
collects/scribblings/style/testing.scrbl
Normal file
71
collects/scribblings/style/testing.scrbl
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#lang scribble/base
|
||||||
|
|
||||||
|
@(require "shared.rkt")
|
||||||
|
|
||||||
|
@title[#:tag "testing"]{Testing}
|
||||||
|
|
||||||
|
@; -----------------------------------------------------------------------------
|
||||||
|
@section[#:tag "test-suite"]{Test Suites}
|
||||||
|
|
||||||
|
Most of our collections come with test suites. These tests suites tend to
|
||||||
|
live in @tt{collects/tests/} in the PLT repository, though due to
|
||||||
|
historical reasons, a few collections come with their own local test
|
||||||
|
suites. If you add a new collection, create a new test suite in the
|
||||||
|
@tt{tests} collection.
|
||||||
|
|
||||||
|
Run the test suites before you commit. To facilitate testing, we urge you
|
||||||
|
to add a @tt{TESTME.txt} file to your collections. Ideally, you may also
|
||||||
|
wish to have a file in this directory that runs the basic tests. See the
|
||||||
|
@hyperlink["https://github.com/plt/racket/tree/master/collects/2htdp/"]{2htdp},
|
||||||
|
which is one of the collections with own testing style. The file should
|
||||||
|
describe where the tests are located, how to run thee tests, and what to
|
||||||
|
look for in terms of successes and failures. These files are necessary
|
||||||
|
because different collections have different needs for testing, and
|
||||||
|
testing evolved in many different ways in our history.
|
||||||
|
|
||||||
|
After you commit, watch for and read(!)
|
||||||
|
@hyperlink["http://drdr.racket-lang.org/"]{DrDr}'s emails. Do @emph{not}
|
||||||
|
ignore them. If you have tests that are known to fail and fixing this
|
||||||
|
requires a lot of work, consider splitting your test directory into two
|
||||||
|
parts: @tt{success} and @tt{failure}. The former is for tests that should
|
||||||
|
succeed now, and the latter is for tests that are currently expected to
|
||||||
|
fail. See the
|
||||||
|
@hyperlink["https://github.com/plt/racket/tree/master/collects/tests/typed-scheme"]{Typed
|
||||||
|
Racket testing arrangement} for an example.
|
||||||
|
|
||||||
|
@; -----------------------------------------------------------------------------
|
||||||
|
@section[#:tag "test-bang"]{Always Test!}
|
||||||
|
|
||||||
|
When you debug an existing piece of code, formulate a test case first. Put
|
||||||
|
it into the test suite for the component so the mistake will never be
|
||||||
|
accidentally re-introduced and add a note that points to the problem
|
||||||
|
report. Second, modify the code to fix the mistake. Do this second to be
|
||||||
|
sure you didn't introduce a mistake in your tests; it is all too easy to
|
||||||
|
think you have fixed a mistake when in reality your new test just doesn't
|
||||||
|
properly reveal the old mistake. Third, re-run the test suite to ensure
|
||||||
|
that the mistake is fixed and no existing tests fail.
|
||||||
|
|
||||||
|
If there is no test suite and you aren't sure how to build one, then ask on
|
||||||
|
the developer mailing list. Perhaps people will explain why there isn't
|
||||||
|
one or they will sketch how to create one. Please don't ignore the
|
||||||
|
problem. If you cannot build a test suite, you have a few options:
|
||||||
|
|
||||||
|
@itemlist[#:style 'ordered
|
||||||
|
|
||||||
|
@item{Add functionality to the library to enable testing. Of course,
|
||||||
|
adding functionality means adding external documentation. Robby and
|
||||||
|
Matthew have done so for the GUI library, and there is now a large
|
||||||
|
automated test suite for DrRacket. So even GUI programs can come with
|
||||||
|
extended test suites.}
|
||||||
|
|
||||||
|
@item{Add an end-to-end test that may have to be verified by a human.
|
||||||
|
For example, it might be hard to test Slideshow, so you could create a
|
||||||
|
slide set and describe what it should look like so future maintainers to
|
||||||
|
verify when @emph{they} make changes. Consider this the @emph{last and
|
||||||
|
least desirable} option, however.}
|
||||||
|
]
|
||||||
|
@;
|
||||||
|
The lack of tests for some collection will not disappear overnight. But if
|
||||||
|
we all contribute a little bit, we will eventually expand the test suites
|
||||||
|
to cover the entire code base, and future generations of maintainers will
|
||||||
|
be grateful.
|
|
@ -120,6 +120,17 @@ patient and use the existing indentation tool anyway.
|
||||||
|
|
||||||
@bold{Caveat 2}: This rule does not apply to scribble code.
|
@bold{Caveat 2}: This rule does not apply to scribble code.
|
||||||
|
|
||||||
|
@; -----------------------------------------------------------------------------
|
||||||
|
@section{Tabs}
|
||||||
|
|
||||||
|
Do not use tab characters in your code. Tabs make it hard to use textual
|
||||||
|
tools like git or diff effectively. To disable tabs,
|
||||||
|
@itemlist[
|
||||||
|
@item{in DrRacket: you are all set. It doesn't insert tabs.}
|
||||||
|
@item{in Emacs: add (setq indent-tabs-mode nil) to your emacs initialization file.}
|
||||||
|
@item{in vi: set expandtab.}
|
||||||
|
]
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
@section{Line Breaks}
|
@section{Line Breaks}
|
||||||
|
|
||||||
|
@ -192,18 +203,17 @@ racket
|
||||||
|
|
||||||
(code:comment #, @t{and})
|
(code:comment #, @t{and})
|
||||||
|
|
||||||
(composition img
|
(above img
|
||||||
(- width hdelta)
|
(- width hdelta)
|
||||||
(- height vdelta)
|
(- height vdelta)
|
||||||
bg)
|
bg)
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@racketmod[#:file
|
@racketmod[#:file
|
||||||
@tt{bad}
|
@tt{bad}
|
||||||
racket
|
racket
|
||||||
|
|
||||||
(composition ufo
|
(above ufo
|
||||||
10 v-delta bg)
|
10 v-delta bg)
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
@ -281,7 +291,8 @@ traverse_forest
|
||||||
]
|
]
|
||||||
@;
|
@;
|
||||||
Note that _ (the underline character) is also classified as bad
|
Note that _ (the underline character) is also classified as bad
|
||||||
Racketeering.
|
Racketeering within names. It is an acceptable placeholder in syntax
|
||||||
|
patterns, match patterns, and parameters that don't matter.
|
||||||
|
|
||||||
Another widely used convention is to @emph{prefix} a function name with the data
|
Another widely used convention is to @emph{prefix} a function name with the data
|
||||||
type of the main argument. This convention generalizes the selector-style
|
type of the main argument. This convention generalizes the selector-style
|
||||||
|
@ -331,7 +342,7 @@ Finally, in addition to regular alphanumeric characters, Racketeers use a
|
||||||
@row[<%> "interfaces" dc<%>]
|
@row[<%> "interfaces" dc<%>]
|
||||||
@row[^ "unit signatures" game-context^]
|
@row[^ "unit signatures" game-context^]
|
||||||
@row["@" "units" testing-context@]
|
@row["@" "units" testing-context@]
|
||||||
@row["#%" "kernel identifiers" #:app]
|
@row["#%" "kernel identifiers" #%app]
|
||||||
]
|
]
|
||||||
The use of ``#%'' to prefix names from the kernel language warns readers
|
The use of ``#%'' to prefix names from the kernel language warns readers
|
||||||
that these identifiers are extremely special and they need to watch out
|
that these identifiers are extremely special and they need to watch out
|
||||||
|
@ -350,7 +361,7 @@ may relax this constraint.
|
||||||
|
|
||||||
@section{Spaces}
|
@section{Spaces}
|
||||||
|
|
||||||
Don't pollute your code with spaces and extraneous blank lines.
|
Don't pollute your code with spaces at the end of lines and extraneous blank lines.
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
@section{End of File}
|
@section{End of File}
|
||||||
|
|
|
@ -8,12 +8,6 @@
|
||||||
|
|
||||||
@item{Write a section on when macros, when functions.}
|
@item{Write a section on when macros, when functions.}
|
||||||
|
|
||||||
@item{Write a section on how to organize test suites --
|
|
||||||
|
|
||||||
Robby: please review the "correctness" section (1.1) and determine what we
|
|
||||||
need to add. It turns out that the point showed up in several feedback
|
|
||||||
messages so a hand-wavy thing is probably not enough.}
|
|
||||||
|
|
||||||
@item{Write a section on how to design test cases.}
|
@item{Write a section on how to design test cases.}
|
||||||
|
|
||||||
@item{Write a section on how to check the stressability of your software.}
|
@item{Write a section on how to check the stressability of your software.}
|
||||||
|
@ -22,9 +16,4 @@ messages so a hand-wavy thing is probably not enough.}
|
||||||
|
|
||||||
@item{Do we need a discussion of life cycles that start in @tt{unstable}?}
|
@item{Do we need a discussion of life cycles that start in @tt{unstable}?}
|
||||||
|
|
||||||
@item{The section on comments (constructs) should be expanded to cover
|
|
||||||
S-expression comments etc. --
|
|
||||||
|
|
||||||
Eli: you seem to have good ideas. Please write up an explanation.}
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -138,7 +138,7 @@ Avoid @racket[(provide (all-defined-out))] except for general-purpose
|
||||||
libraries.
|
libraries.
|
||||||
|
|
||||||
A test suite section---if located within the module---should come at the
|
A test suite section---if located within the module---should come at the
|
||||||
every end, including its specific dependencies, i.e., @racket[require]
|
very end, including its specific dependencies, i.e., @racket[require]
|
||||||
specifications.
|
specifications.
|
||||||
|
|
||||||
@; -----------------------------------------------------------------------------
|
@; -----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user