Skip to content

Commit 5df0b1a

Browse files
committed
added more content on end-to-end testing, env variables, and Java properties
Signed-off-by: Konstantin Läufer <[email protected]>
1 parent 2fe5f8b commit 5df0b1a

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

source/imperative.rst

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,55 @@ If your coverage percentages appear low, you can make them more accurate by excl
198198
Additional information on testing is available in the corresponding section of the `COMP 335/435: Formal Methods lecture notes <https://lucformalmethodscourse.github.io/30-testing.html>`_.
199199

200200

201+
End-to-end application testing
202+
``````````````````````````````
203+
204+
Besides the familiar styles of unit testing, one could attempt to automate the process of end-to-end application testing.
205+
One approach would be to use shell scripts in conjunction with sample input and expected output files;
206+
after running the application on the sample input, one could use a ``diff`` utility to compare the actual output to the expected output.
207+
208+
This approach adds complexity in terms of maintaining an additional set of data files, however, and it is brittle in that the test may no longer be valid after changes in the output format of the application under test.
209+
Therefore, it is usually preferable to use the unit testing techniques described above at the data structure level as opposed to comparing formatted output.
210+
211+
On the other hand, if one really wants to test the I/O code, one could set up programmatic end-to-end application tests as part of an automated test suite by redirecting the standard input and output to in-memory streams one can populate or examine programmatically.
212+
This approach appears to work within IDEs such as IntelliJ but not in a standalone invocation of sbt.
213+
214+
.. code-block:: scala
215+
216+
@Test
217+
def testMainEndToEnd: Unit =
218+
val ba = new ByteArrayOutputStream
219+
val os = new PrintStream(ba)
220+
System.setOut(os) // redirect stdout to the in-memory stream
221+
main.Main.main(Array.empty[String])
222+
val lines =
223+
import scala.language.unsafeNulls
224+
ba.toString.lines.toList.asScala
225+
assertEquals("hello", lines(0))
226+
assertEquals("hello hello", lines(1))
227+
228+
201229
The role of console applications
202230
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203231

204232
Console applications have always been an important part of the UNIX command-line environment.
233+
Each application typically focuses on a specific task, and several applications can be composed to solve a more complex task.
234+
205235
The typical console application interacts with its environment in the following ways:
206236

237+
- *environment variables* defined in your system
207238
- zero or more application-specific *command-line arguments* for passing options to the application: ``app arg1 arg2 ...``
208239
- *standard input* (stdin) for reading the input data
209240
- *standard output* (stdout) for writing the output data
210241
- *standard error* (stderr) for displaying error messages separately from the output data
211242

212-
Applications written in this way can function as composable building blocks using UNIX pipes.
213-
Using these standard I/O mechanisms is much more flexible than reading from or writing to files whose names are hardcoded in the program.
243+
From a Scala perspective, environment variables are accessible via the predefined ``sys.env`` map, e.g., ``sys.env("HOME")``, and command-line arguments are accessible via the main method's argument ``args`` (a string array).
244+
Similar mechanisms are available in Java and other JVM languages.
245+
246+
.. note:: In addition, languages running on a Java Virtual Machine (JVM) support *properties* defined through command-line arguments of the form ``-Dmy.prop=someValue`` and accessible via, e.g., ``sys.props("my.prop")``.
247+
248+
Applications that read and write from and to the standard data streams can function as composable building blocks using UNIX pipes.
249+
Using these standard I/O mechanisms is much more flexible than reading from or writing to specific files whose names are hardcoded in the program.
214250

215251
E.g., the ``yes`` command outputs its arguments forever on consecutive output lines,
216252
the ``head`` command outputs a finite prefix of its input,

0 commit comments

Comments
 (0)