You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source/imperative.rst
+38-2Lines changed: 38 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -198,19 +198,55 @@ If your coverage percentages appear low, you can make them more accurate by excl
198
198
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>`_.
199
199
200
200
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
+
201
229
The role of console applications
202
230
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203
231
204
232
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
+
205
235
The typical console application interacts with its environment in the following ways:
206
236
237
+
- *environment variables* defined in your system
207
238
- zero or more application-specific *command-line arguments* for passing options to the application: ``app arg1 arg2 ...``
208
239
- *standard input* (stdin) for reading the input data
209
240
- *standard output* (stdout) for writing the output data
210
241
- *standard error* (stderr) for displaying error messages separately from the output data
211
242
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.
214
250
215
251
E.g., the ``yes`` command outputs its arguments forever on consecutive output lines,
216
252
the ``head`` command outputs a finite prefix of its input,
0 commit comments