summaryrefslogtreecommitdiffstats
path: root/2023/info/test-after.md
diff options
context:
space:
mode:
Diffstat (limited to '2023/info/test-after.md')
-rw-r--r--2023/info/test-after.md991
1 files changed, 991 insertions, 0 deletions
diff --git a/2023/info/test-after.md b/2023/info/test-after.md
new file mode 100644
index 00000000..413f1f6d
--- /dev/null
+++ b/2023/info/test-after.md
@@ -0,0 +1,991 @@
+<!-- Automatically generated by emacsconf-publish-after-page -->
+
+
+<a name="test-mainVideo-transcript"></a>
+# Transcript
+
+
+[[!template new="1" text="""Introduction""" start="00:00:03.120" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Hi everyone! I'm Mats Lidell.""" start="00:00:03.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I'm going to talk about my journey""" start="00:00:07.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""writing test cases for GNU Hyperbole""" start="00:00:09.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and what I learned on the way.""" start="00:00:12.481" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So, why write tests for GNU Hyperbole?""" start="00:00:19.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""There is some background.""" start="00:00:24.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I'm the co-maintainer of GNU Hyperbole""" start="00:00:25.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""together with Bob Weiner. Bob is the author of the package.""" start="00:00:27.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The package is available through""" start="00:00:33.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the Emacs package manager and GNU Elpa""" start="00:00:34.681" video="mainVideo-test" id="subtitle"]]
+[[!template text="""if you would want to try it out.""" start="00:00:38.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The package has some age. I think it dates back to""" start="00:00:42.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""a first release around 1993, which is also""" start="00:00:46.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""when I got in contact with the package the first time.""" start="00:00:50.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I was a user of the package for many years.""" start="00:00:54.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Later, I became the maintainer of the package for the FSF.""" start="00:00:58.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That was although I did not have""" start="00:01:03.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""much knowledge of Emacs Lisp,""" start="00:01:04.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and I still have a lot to learn.""" start="00:01:09.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""A few years ago, we started to work actively on the package,""" start="00:01:12.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with setting up goals and having meetings.""" start="00:01:15.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So my starting point is that I had experience""" start="00:01:20.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with test automation from development""" start="00:01:24.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""in C++, Java and Python""" start="00:01:27.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""using different x-unit frameworks like cppunit, junit.""" start="00:01:30.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That was in my daytime work where""" start="00:01:37.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the technique of using pull requests""" start="00:01:40.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with changes backed up by tests were the daily routine.""" start="00:01:41.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It was really a requirement for a change to go in""" start="00:01:46.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to have supporting test cases.""" start="00:01:49.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I believe, a quite common setup and requirement these days.""" start="00:01:52.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I also had been an Emacs user for many years,""" start="00:01:58.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but with focus on being a user.""" start="00:02:02.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So as I mentioned, I have limited Emacs Lisp knowledge.""" start="00:02:04.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""When we decided to start""" start="00:02:09.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to work actively on Hyperbole again,""" start="00:02:11.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it was natural for me to look into""" start="00:02:13.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""raising the quality by adding unit tests.""" start="00:02:15.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This also goes hand in hand""" start="00:02:18.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with running these regularly as part of a build process.""" start="00:02:20.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""All in all, following the current best practice""" start="00:02:25.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""of software development.""" start="00:02:28.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""But since Hyperbole had no tests at all,""" start="00:02:31.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it would not be enough just to add tests""" start="00:02:36.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""for new or changed functionality.""" start="00:02:38.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We wanted to add it even broader; ideally, everywhere.""" start="00:02:41.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So work started with adding tests here and there""" start="00:02:44.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""based on our gut feeling where it would be most useful.""" start="00:02:48.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This work is still ongoing.""" start="00:02:52.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So this is where my journey starts""" start="00:02:55.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with much functionality to test,""" start="00:02:58.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""no knowledge of what testing frameworks existed,""" start="00:03:00.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and not really knowing a lot about Emacs Lisp at all.""" start="00:03:03.360" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""ERT: Emacs Lisp Regression Testing""" start="00:03:11.160" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Luckily there is a package for writing tests in Emacs.""" start="00:03:11.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It is called ERT: Emacs Lisp Regression Testing.""" start="00:03:13.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It contains both support for defining tests and running them.""" start="00:03:17.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Defining a test is done with the macro `ert-deftest`.""" start="00:03:20.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In its simplest form, a test has a name, a doc string, and a body.""" start="00:03:24.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The doc string is where you typically can give""" start="00:03:28.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""a detailed description of the test""" start="00:03:31.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and has space for more info""" start="00:03:33.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""than what can be given in the test name.""" start="00:03:35.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The body is where all the interesting things happen.""" start="00:03:42.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It is here you prepare the test, run it and verify the outcome.""" start="00:03:45.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Schematically, it looks like this.""" start="00:03:51.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""You have the ert-deftest, you have the test name,""" start="00:03:54.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and the doc string, and then the body.""" start="00:04:00.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It is in the body where everything interesting happens.""" start="00:04:02.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The test is prepared, the function of the test is executed,""" start="00:04:06.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and the outcome of the test is evaluated.""" start="00:04:09.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Did the test succeed or not?""" start="00:04:13.120" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Assertions with `should`""" start="00:04:14.360" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""The verification of a test is performed with""" start="00:04:14.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""one or more so-called assertions.""" start="00:04:18.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In ERT, they are implemented""" start="00:04:21.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with the macro `should`""" start="00:04:25.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""together with a set of related macros.""" start="00:04:26.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""`should` takes a form as argument,""" start="00:04:33.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and if the form evaluates to nil,""" start="00:04:35.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the test has failed. So let's look at an example.""" start="00:04:37.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This simple test verifies that the function `+`""" start="00:04:48.581" video="mainVideo-test" id="subtitle"]]
+[[!template text="""can add the numbers 2 and 3 and get the result 5.""" start="00:04:51.920" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Running a test case""" start="00:04:56.920" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""So now we have defined a test case. How do we run it?""" start="00:04:56.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The ERT package has the function (or""" start="00:05:01.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""rather convenience alias) `ert`. It takes a test selector.""" start="00:05:03.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The test name works as a selector for running just one test.""" start="00:05:09.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So here we have the example. Let's evaluate it.""" start="00:05:19.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We define it and then we run it using ERT.""" start="00:05:27.901" video="mainVideo-test" id="subtitle"]]
+[[!template text="""As you see, we get prompted for a test selector""" start="00:05:34.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but we only have one test case defined at the moment.""" start="00:05:42.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It's the example 0. So let's hit RET.""" start="00:05:46.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""As you see here, we get some output""" start="00:05:55.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""describing what we have just done.""" start="00:05:58.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""There is one test case it has passed, zero failed,""" start="00:06:01.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""zero skipped, total 1 of 1 test case""" start="00:06:04.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and some time stamps for the execution.""" start="00:06:07.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We also see this green mark here indicating one test case""" start="00:06:14.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and that it was successful.""" start="00:06:18.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""For inspecting the test, we can hit the letter `l`""" start="00:06:23.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""which shows all the `should` forms""" start="00:06:29.660" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that was executed during this test case.""" start="00:06:32.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So here we see that we have the `should`,""" start="00:06:37.780" video="mainVideo-test" id="subtitle"]]
+[[!template text="""one `should` executed, and we see the form equals to 2,""" start="00:06:39.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and it was 5 equals to 5.""" start="00:06:48.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So a good example of a successful test case.""" start="00:06:49.800" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Debug a test""" start="00:06:54.560" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""So now we've seen how we can run a test case.""" start="00:06:54.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Can we debug it? Yes. For debugging a test case,""" start="00:06:57.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the `ert-deftest` can be set up using `edebug-defun`,""" start="00:07:03.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""just as a function or macro is set up""" start="00:07:07.940" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or instrumented for debugging. So let's try that.""" start="00:07:10.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So we try `edebug-defun` here.""" start="00:07:18.820" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Now it's instrumented for debugging.""" start="00:07:24.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And we run it, `ert`, and we're inside the debugger,""" start="00:07:28.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and we can inspect here what's happening.""" start="00:07:35.660" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Step through it and yes it succeeded just as before.""" start="00:07:40.680" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Commercial break: Hyperbole""" start="00:07:50.380" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""It's time for a commercial break!""" start="00:07:50.380" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Hyperbole itself can help with running tests""" start="00:07:56.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and also help with running them in debug mode.""" start="00:08:00.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That is because hyperbole identifies the `ert-deftest`""" start="00:08:03.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""as an implicit button. An implicit button is basically""" start="00:08:08.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""a string or pattern""" start="00:08:12.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that Hyperbole has assigned some meaning to.""" start="00:08:13.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""For the string `ert-deftest`, it is to run the test case.""" start="00:08:16.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""You activate the button with the action-key.""" start="00:08:19.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The standard binding is the middle mouse button,""" start="00:08:24.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or from the keyboard, M-RET.""" start="00:08:27.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So let's try that.""" start="00:08:33.041" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We move the cursor here and then we type M-RET.""" start="00:08:34.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And boom, the test case was executed.""" start="00:08:42.220" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And to run it in debug mode we type C-u M-RET""" start="00:08:47.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to get the assist key, and then we're in the debugger.""" start="00:08:54.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So that's pretty useful and convenient.""" start="00:08:57.720" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Instrument function on the fly""" start="00:09:10.480" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""A related useful feature here is the step-in functionality""" start="00:09:10.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""bound to the letter i in `debug-mode`.""" start="00:09:13.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It allows you to step into a function""" start="00:09:16.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and continue debugging from there.""" start="00:09:18.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""For the cases where your test does not do what you want,""" start="00:09:20.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""looking at what happens in the function of the test""" start="00:09:22.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""can be really useful. Let's try that with another example.""" start="00:09:25.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So here we have two helper functions, one `f1-add`,""" start="00:09:37.260" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that use the built-in `+` function""" start="00:09:43.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and then we have `my-add` that uses that function.""" start="00:09:47.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So we're going to test myadd.""" start="00:09:52.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And then let's run this.""" start="00:09:59.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's run this using hyperbole in debug mode""" start="00:10:02.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""C-u M-RET. We're in the debugger again,""" start="00:10:05.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and let's step up front to my function under test""" start="00:10:10.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and then press `i` for getting it instrumented""" start="00:10:15.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and going into it for debugging.""" start="00:10:19.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And here we can expect that it's getting""" start="00:10:23.020" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the arguments 1 and 3,""" start="00:10:25.140" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and it returns the result 4 as expected.""" start="00:10:26.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And yes, of course, our test case will then succeed.""" start="00:10:31.000" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Mocking""" start="00:10:39.120" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""The next tool in our toolbox is mocking.""" start="00:10:39.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Mocking is needed when we want to simulate the response""" start="00:10:41.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""from a function used by the function under test.""" start="00:10:46.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That is the implementation of the function.""" start="00:10:49.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This could be for various reasons.""" start="00:10:53.140" video="mainVideo-test" id="subtitle"]]
+[[!template text="""One example could be because it would be hard or impossible""" start="00:10:56.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""in the test setup to get the behavior you want to test for,""" start="00:11:00.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""like an external error case.""" start="00:11:04.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""But the mock can also be used to verify""" start="00:11:06.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that the function is called with a specific argument.""" start="00:11:08.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We can view it as a way to isolate the function on the test""" start="00:11:11.620" video="mainVideo-test" id="subtitle"]]
+[[!template text="""from its dependencies.""" start="00:11:14.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So in order to test the function in isolation,""" start="00:11:16.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""we need to cut out any dependencies to external behavior.""" start="00:11:18.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Most obvious would be dependencies to external resources,""" start="00:11:22.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""such as web pages. As an example:""" start="00:11:25.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Hyperbole contains functionality to link you to""" start="00:11:27.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""social media resources and other resources on the net.""" start="00:11:30.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Testing that would require the test system to call out""" start="00:11:34.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to the social media resources""" start="00:11:37.900" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and would depend on it being available, etc.""" start="00:11:39.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Nothing technically stops a test case""" start="00:11:43.540" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to depend on the external resources,""" start="00:11:45.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but would, if nothing else, be flaky or slow.""" start="00:11:47.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It could be part of an end-to-end suite""" start="00:11:51.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""where we want to test that it works all the way.""" start="00:11:53.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In this case, we want to look at the isolated case""" start="00:11:57.180" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that can be run with no dependency on external resources.""" start="00:11:59.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""What you want to do is to replace the function with a mock""" start="00:12:04.100" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that behaves as the real function would do.""" start="00:12:06.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The package I have found""" start="00:12:10.340" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and have used for mocking is `el-mock`.""" start="00:12:11.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The workhorse in this package is the `with-mock` macro.""" start="00:12:14.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It looks like this: `with-mock` followed by a body.""" start="00:12:21.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In the execution of the body, stubs and mocks""" start="00:12:26.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""defined in the body is respected.""" start="00:12:30.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's look at some examples to make that clearer.""" start="00:12:32.900" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In this case, we have the macro `with-mock`.""" start="00:12:39.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It works so that the expression""" start="00:12:42.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""`stub + => 10` is interpreted""" start="00:12:43.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so that the function `+` will be replaced with the stub.""" start="00:12:48.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The stub will return 10 regardless how it is called.""" start="00:12:51.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Note that the stub function""" start="00:12:56.780" video="mainVideo-test" id="subtitle"]]
+[[!template text="""does not have to be called at this level""" start="00:12:58.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but could be called at any level in the call chain.""" start="00:13:00.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""By knowing how the function under test is implemented""" start="00:13:02.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and how the implementation works,""" start="00:13:07.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""you can find function calls you want to mock""" start="00:13:09.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to force certain behavior that you want to test,""" start="00:13:11.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or to avoid calls to external resources, slow calls, etc.""" start="00:13:15.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Simply isolate the function under test""" start="00:13:19.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and simulate its environment.""" start="00:13:21.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Mock is a little bit more sophisticated""" start="00:13:26.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and depends on the arguments""" start="00:13:28.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that the mock function is called with.""" start="00:13:30.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Or more precise, it is checked""" start="00:13:31.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""after the `with-mock` clause""" start="00:13:33.848" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that the arguments match the arguments it was called with""" start="00:13:35.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or even if it was called at all.""" start="00:13:38.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""If it is called with other arguments""" start="00:13:39.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""there will be an error,""" start="00:13:41.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and if it's not called, it is also an error.""" start="00:13:43.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So this way, we are sure that the function""" start="00:13:46.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""we were expected to be called actually was called.""" start="00:13:48.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""An important piece of the testing.""" start="00:13:51.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So we are sure that the mock we have provided""" start="00:13:53.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""actually is triggered by the test case.""" start="00:13:56.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So here we have an example of `with-mock`""" start="00:14:04.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""where the `f1-add` function is mocked,""" start="00:14:08.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so that if it's called with 2 and 3 as arguments,""" start="00:14:18.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it will return 10. Then we have a test case""" start="00:14:22.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""where we try the `my-add` function,""" start="00:14:24.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""as you might remember, and call that with 2 and 3""" start="00:14:28.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and see that it should also then return 10""" start="00:14:30.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""because it's using `f1-add`.""" start="00:14:32.800" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""cl-letf""" start="00:14:41.240" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Moving over to `cl-letf`.""" start="00:14:41.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In rare occasions, the limitations of `el-mock` means""" start="00:14:44.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""you would want to implement a full-fledged function""" start="00:14:47.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to be used under test.""" start="00:14:50.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Then the macro `cl-letf` can be useful.""" start="00:14:52.980" video="mainVideo-test" id="subtitle"]]
+[[!template text="""However, you need to handle the case yourself""" start="00:14:55.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""if the function was not called.""" start="00:14:57.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Looking through the test cases where I have used `cl-letf`,""" start="00:15:00.100" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I think most can be implemented using plain mocking.""" start="00:15:03.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Cases left is where the args to the mock might be different""" start="00:15:06.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""due to environment issues.""" start="00:15:11.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In that case, a static mock will not work.""" start="00:15:13.740" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Hooks""" start="00:15:24.100" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Another trick is that functions that uses hooks.""" start="00:15:24.100" video="mainVideo-test" id="subtitle"]]
+[[!template text="""You can overload or replace the hooks to do the testing.""" start="00:15:30.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So you can use the hook function just to do the verification""" start="00:15:35.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and not do anything useful in the hook.""" start="00:15:40.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Also, here you need to be careful""" start="00:15:43.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to make sure the test handler is called and nothing else.""" start="00:15:45.080" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Side effects and initial buffer state""" start="00:15:55.720" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""So far we have been talking about testing""" start="00:15:55.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and what the function returns.""" start="00:15:57.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In the best of words, we have a pure function""" start="00:15:59.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that only depends on its arguments""" start="00:16:01.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and produces no side effects.""" start="00:16:02.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Many operations produce side effects""" start="00:16:04.940" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or operate on the contents of buffers""" start="00:16:06.900" video="mainVideo-test" id="subtitle"]]
+[[!template text="""such as writing a message in the message buffer,""" start="00:16:09.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""change the state of a buffer, move point etc.""" start="00:16:12.380" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Hyperbole is not an exception. Quite the contrary.""" start="00:16:15.660" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Much of the functions creating links""" start="00:16:18.860" video="mainVideo-test" id="subtitle"]]
+[[!template text="""are just about updating buffers.""" start="00:16:20.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This poses a special problem for tests.""" start="00:16:24.421" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The test gets longer""" start="00:16:28.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""since you need to create buffers and files,""" start="00:16:29.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""initialize the contents.""" start="00:16:31.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Verifying the outcome becomes trickier""" start="00:16:33.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""since you need to make sure you look at the right place.""" start="00:16:35.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""At the end of the test, you need to clean up,""" start="00:16:39.020" video="mainVideo-test" id="subtitle"]]
+[[!template text="""both for not leaving a lot of garbage""" start="00:16:41.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""in buffers and files around,""" start="00:16:43.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and even worse, not cause later tests""" start="00:16:45.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to depend on the leftovers from the other tests.""" start="00:16:48.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Here are some functions and variables""" start="00:16:50.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I have found useful for this.""" start="00:16:53.080" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""with-temp-buffer""" start="00:17:05.100" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""For creating tests: `with-temp-buffer`:""" start="00:17:05.100" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it provides you a temp buffer that you visit,""" start="00:17:09.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and afterwards, there is no need to clean up.""" start="00:17:11.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This is the first choice if that is all you need.""" start="00:17:13.720" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""make-temp-file""" start="00:17:16.520" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""`make-temp-file`: If you need a file,""" start="00:17:16.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""this is the function to use.""" start="00:17:20.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It creates a temp file or a directory.""" start="00:17:21.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The file can be filled with initial contents.""" start="00:17:24.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This needs to be cleaned up after a test.""" start="00:17:26.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Moving on to verifying and debugging:""" start="00:17:31.020" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""buffer-string""" start="00:17:33.288" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""`buffer-string`: returns the full contents""" start="00:17:33.288" video="mainVideo-test" id="subtitle"]]
+[[!template text="""of the buffer as a string.""" start="00:17:38.248" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That can sound a bit voluminous,""" start="00:17:39.500" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but since tests are normally small, this often works well.""" start="00:17:41.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I have in particular found good use of comparing""" start="00:17:46.140" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the contents of buffers with the empty string.""" start="00:17:48.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That would give an error, but as we have seen""" start="00:17:50.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with the output produced by the `should` assertion,""" start="00:17:53.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""this is almost like a print statement""" start="00:17:56.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and can be compared with the good old technique""" start="00:17:58.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""of debugging with print statements.""" start="00:18:01.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""There might be other ways to do the same""" start="00:18:04.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""as we saw with debugging.""" start="00:18:06.248" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""buffer-name""" start="00:18:09.920" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""buffer-name: Getting the buffer name is good""" start="00:18:09.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to verify what buffer we are looking at.""" start="00:18:13.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I often found it useful to check""" start="00:18:16.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that my assumptions on what buffer I am acting on""" start="00:18:18.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""is correct by adding `should` clauses""" start="00:18:21.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""in the middle of the test execution""" start="00:18:23.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or after preparing the test input.""" start="00:18:25.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Sometimes Emacs can switch buffers in strange ways,""" start="00:18:27.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""maybe because the test case is badly written,""" start="00:18:31.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and making sure your assumptions are correct""" start="00:18:34.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""is a good sanity check.""" start="00:18:37.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Even the ert package does""" start="00:18:40.340" video="mainVideo-test" id="subtitle"]]
+[[!template text="""some buffer and windows manipulation for its reporting""" start="00:18:42.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that I have not fully learned how to master,""" start="00:18:44.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so assertion for checking the sanity of the test is good.""" start="00:18:47.488" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""major-mode""" start="00:18:51.980" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Finally, `major-mode`: Verify the buffer has the proper mode.""" start="00:18:51.980" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Can also be very useful and is a good sanity check.""" start="00:18:55.680" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""unwind-protect""" start="00:19:02.680" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Finally, cleaning up. `unwind-protect`.""" start="00:19:02.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The tool for cleaning up is the `unwind-protect` form""" start="00:19:06.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""which ensures that the unwind forms""" start="00:19:09.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""always are executed regardless of the outcome of the body.""" start="00:19:12.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So if your test fails, you are sure the cleanup is executed.""" start="00:19:15.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's look at unwind-protect together with""" start="00:19:20.420" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the temporary file example. Many tests look like this.""" start="00:19:22.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""You create some resource, you call `unwind-protect`,""" start="00:19:30.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""you do the test, and then afterwards you do the cleanup.""" start="00:19:35.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The cleanup for a file and a buffer is so common,""" start="00:19:42.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so I have created a helper for that.""" start="00:19:46.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It looks like this.""" start="00:19:51.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The trick with the `buffer-modified` flag""" start="00:19:56.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""is to avoid getting prompted""" start="00:19:59.180" video="mainVideo-test" id="subtitle"]]
+[[!template text="""for killing a buffer that is not saved.""" start="00:20:00.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The test buffers are often in the state""" start="00:20:03.220" video="mainVideo-test" id="subtitle"]]
+[[!template text="""where they have not been saved but modified.""" start="00:20:05.440" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Input, with-simulated-input""" start="00:20:15.100" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Another problem for tests are input.""" start="00:20:15.100" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In the middle of execution a function""" start="00:20:19.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""might want to have some interaction with the user.""" start="00:20:21.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Testing this poses a problem, not only in that""" start="00:20:24.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""the input matters, but also as how even to get the test case""" start="00:20:26.960" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to recognize the input!?""" start="00:20:31.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Ideally the tests are run in batch mode,""" start="00:20:34.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""which in some sense means no user interaction.""" start="00:20:36.040" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In batch mode, there is no event loop running.""" start="00:20:38.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Fortunately, there is a package `with-simulated-input`""" start="00:20:43.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that gets you around these issues.""" start="00:20:47.180" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This is a macro that allows us""" start="00:20:53.260" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to define a set of characters""" start="00:20:55.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that will be read by the function under the test,""" start="00:20:57.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and all of this works in batch mode. It looks like this.""" start="00:20:59.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We have `with-simulated-input`,""" start="00:21:02.580" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and then a string of characters, and then a body.""" start="00:21:04.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The form takes a string of keys""" start="00:21:09.840" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and runs the rest of the body,""" start="00:21:11.648" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and if there are input required,""" start="00:21:13.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it is picked from the string of keys.""" start="00:21:15.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""In our example, the `read-string` call""" start="00:21:18.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""will read up until RET,""" start="00:21:20.422" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and then return the characters read.""" start="00:21:21.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""As you see in the example, space needs to be provided""" start="00:21:26.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""by the string SPC, as return by the string RET.""" start="00:21:29.640" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Running all tests""" start="00:21:38.460" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""So now we have seen ways to create test cases""" start="00:21:38.460" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and even make it possible to run some of them""" start="00:21:40.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that has I/O in batch mode.""" start="00:21:43.220" video="mainVideo-test" id="subtitle"]]
+[[!template text="""But the initial goal was to run them all at once.""" start="00:21:44.680" video="mainVideo-test" id="subtitle"]]
+[[!template text="""How do you do that?""" start="00:21:47.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's go back to the `ert` command.""" start="00:21:48.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""It prompts for a test selector.""" start="00:21:51.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""If we give it the selector `t`,""" start="00:21:53.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it will run all tests we have currently defined.""" start="00:21:56.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's try that with the subset of the Hyperbole tests.""" start="00:21:59.260" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Here is the test folder in the Hyperbole directory.""" start="00:22:05.780" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Let's go up here and load all the demo tests.""" start="00:22:09.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And then try to run `ert`.""" start="00:22:18.820" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Now we see that we have a bunch of test cases.""" start="00:22:21.208" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We can all run them individually,""" start="00:22:26.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but we can run them with `t` instead.""" start="00:22:27.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We will run them all at once.""" start="00:22:31.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So now, ert is executing all our test cases.""" start="00:22:35.460" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So here we have a nice green display""" start="00:22:51.420" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with all the test cases.""" start="00:22:57.080" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Batch mode""" start="00:23:03.220" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""So that was fine, but we were still running it manually""" start="00:23:03.220" video="mainVideo-test" id="subtitle"]]
+[[!template text="""by calling ert. How could we run it from the command line?""" start="00:23:08.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Ert comes with functions for running it in batch mode.""" start="00:23:17.180" video="mainVideo-test" id="subtitle"]]
+[[!template text="""For Hyperbole, we use `make` for repetitive tasks.""" start="00:23:21.500" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So we have a make target""" start="00:23:25.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that uses the ert batch functionality,""" start="00:23:27.120" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and this is the line from the Makefile.""" start="00:23:29.280" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This is a bit detailed,""" start="00:23:33.260" video="mainVideo-test" id="subtitle"]]
+[[!template text="""but you see that we have a part here""" start="00:23:35.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""where we load the test dependencies.""" start="00:23:37.540" video="mainVideo-test" id="subtitle"]]
+[[!template text="""For getting the packages""" start="00:23:40.780" video="mainVideo-test" id="subtitle"]]
+[[!template text="""such as `el-mock` and `with-simulated-input` etc. loaded.""" start="00:23:43.521" video="mainVideo-test" id="subtitle"]]
+[[!template text="""We also have... I also want to point out here the call to""" start="00:23:48.460" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or the setting of `auto-save-default` to `nil`""" start="00:23:53.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to get away with the prompt for excessive backup files""" start="00:23:58.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""that can pile up after running the tests a few times.""" start="00:24:02.440" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Skipping tests""" start="00:24:05.060" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""Even with the help of simulated input,""" start="00:24:05.060" video="mainVideo-test" id="subtitle"]]
+[[!template text="""not all tests can be run in batch mode.""" start="00:24:06.880" video="mainVideo-test" id="subtitle"]]
+[[!template text="""They would simply not work there""" start="00:24:08.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and have to be run in an interactive Emacs""" start="00:24:10.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with the running event loop.""" start="00:24:12.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""One trick still to be able to use batch mode for automation""" start="00:24:14.180" video="mainVideo-test" id="subtitle"]]
+[[!template text="""is to put the guard at the top of each test case""" start="00:24:17.920" video="mainVideo-test" id="subtitle"]]
+[[!template text="""as the first thing to be executed,""" start="00:24:20.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so that it kicks in before anything else and stops Emacs""" start="00:24:22.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to try to run the test case.""" start="00:24:25.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Now, it looks like this: `(skip-unless (not noninteractive))`.""" start="00:24:27.200" video="mainVideo-test" id="subtitle"]]
+[[!template text="""So when ert sees that the test should be skipped, it skips it""" start="00:24:35.520" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and makes a note of that,""" start="00:24:38.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so you will see how many tests that have been skipped.""" start="00:24:40.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Too bad. We have a number of test cases defined,""" start="00:24:44.580" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and to run them, we need to run them manually. Well sort of.""" start="00:24:47.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""Not being able to run all tests easily""" start="00:24:51.360" video="mainVideo-test" id="subtitle"]]
+[[!template text="""is a bit counterproductive""" start="00:24:53.808" video="mainVideo-test" id="subtitle"]]
+[[!template text="""since our goal is to run all tests.""" start="00:24:58.420" video="mainVideo-test" id="subtitle"]]
+[[!template text="""There is however no ert function to run tests in batch mode""" start="00:25:01.000" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with an interactive Emacs.""" start="00:25:04.720" video="mainVideo-test" id="subtitle"]]
+[[!template text="""The closest I have got is either""" start="00:25:06.780" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to start the Emacs from the command line""" start="00:25:08.480" video="mainVideo-test" id="subtitle"]]
+[[!template text="""calling the ert function as we just have seen,""" start="00:25:10.080" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and then killing it manually when done;""" start="00:25:12.440" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or add a function to extract the contents of the ERT buffer""" start="00:25:14.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""when done and echo it to standard output.""" start="00:25:19.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""This is how it looks in the Makefile""" start="00:25:24.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to get the behavior of cutting and paste,""" start="00:25:27.801" video="mainVideo-test" id="subtitle"]]
+[[!template text="""getting the ERT output into a file""" start="00:25:31.208" video="mainVideo-test" id="subtitle"]]
+[[!template text="""so we can then kill Emacs""" start="00:25:34.581" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and spit out the content of the ERT buffer.""" start="00:25:36.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""One final word here is that""" start="00:25:44.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""when you run this in a continuous integration pipeline,""" start="00:25:47.740" video="mainVideo-test" id="subtitle"]]
+[[!template text="""you might not have a TTY for getting Emacs to start,""" start="00:25:54.560" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and that is then another problem""" start="00:25:59.400" video="mainVideo-test" id="subtitle"]]
+[[!template text="""with getting the interactive mode.""" start="00:26:03.201" video="mainVideo-test" id="subtitle"]]
+
+[[!template new="1" text="""Conclusion""" start="00:26:08.460" video="mainVideo-test" id="subtitle"]]
+
+[[!template text="""We have reached the end of the talk.""" start="00:26:08.460" video="mainVideo-test" id="subtitle"]]
+[[!template text="""If you have any new ideas""" start="00:26:11.121" video="mainVideo-test" id="subtitle"]]
+[[!template text="""or have some suggestions for improvements,""" start="00:26:14.160" video="mainVideo-test" id="subtitle"]]
+[[!template text="""feel free to reach out""" start="00:26:16.760" video="mainVideo-test" id="subtitle"]]
+[[!template text="""because I am still on the learning curve of writing,""" start="00:26:18.240" video="mainVideo-test" id="subtitle"]]
+[[!template text="""how to write good test cases.""" start="00:26:21.101" video="mainVideo-test" id="subtitle"]]
+[[!template text="""If you look at the test cases we have in Hyperbole""" start="00:26:25.300" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and you think they might contradict what I am saying here,""" start="00:26:27.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""it is OK. It is probably right.""" start="00:26:29.800" video="mainVideo-test" id="subtitle"]]
+[[!template text="""I have changed the style as I go""" start="00:26:32.580" video="mainVideo-test" id="subtitle"]]
+[[!template text="""and we have not yet refactored all tests""" start="00:26:34.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""to benefit from new designs.""" start="00:26:36.640" video="mainVideo-test" id="subtitle"]]
+[[!template text="""That is also the beauty of the test case.""" start="00:26:38.580" video="mainVideo-test" id="subtitle"]]
+[[!template text="""As long as it serves its purpose, it is not terrible""" start="00:26:40.600" video="mainVideo-test" id="subtitle"]]
+[[!template text="""if it is not optimal or not having the best style.""" start="00:26:43.320" video="mainVideo-test" id="subtitle"]]
+[[!template text="""And yes, thanks for listening. Bye.""" start="00:26:47.800" video="mainVideo-test" id="subtitle"]]
+
+<a name="test-qanda-transcript"></a>
+# Q&A transcript (unedited)
+
+[[!template text="""[Speaker 0]: Do we have any listeners?""" start="00:00:08.740" video="qanda-test" id="subtitle"]]
+[[!template text="""It's you and I. I have a question.""" start="00:00:13.340" video="qanda-test" id="subtitle"]]
+[[!template text="""How many tests do you have for hyperbole and""" start="00:00:16.420" video="qanda-test" id="subtitle"]]
+[[!template text="""How would you rate the test coverage compared""" start="00:00:18.800" video="qanda-test" id="subtitle"]]
+[[!template text="""to other packages? Well,""" start="00:00:21.279" video="qanda-test" id="subtitle"]]
+[[!template text="""that's a tricky 1. Shall I spell it out loud""" start="00:00:28.279" video="qanda-test" id="subtitle"]]
+[[!template text="""and then maybe type it at the same time?""" start="00:00:31.100" video="qanda-test" id="subtitle"]]
+[[!template text="""So, I believe it's around like more than 300""" start="00:00:36.420" video="qanda-test" id="subtitle"]]
+[[!template text="""test cases now. But I cannot compare the test""" start="00:00:43.660" video="qanda-test" id="subtitle"]]
+[[!template text="""coverage to any other""" start="00:00:45.220" video="qanda-test" id="subtitle"]]
+[[!template text="""other package. Maybe I can type that later.""" start="00:01:00.020" video="qanda-test" id="subtitle"]]
+[[!template text="""What do you say, Badal?""" start="00:01:01.560" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: package. I have no knowledge of any Yeah,""" start="00:01:02.660" video="qanda-test" id="subtitle"]]
+[[!template text="""sure, yeah, that's totally fine.""" start="00:01:03.840" video="qanda-test" id="subtitle"]]
+[[!template text="""Feel free to just answer them with voice.""" start="00:01:05.660" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yeah, yeah. There's another question.""" start="00:01:08.720" video="qanda-test" id="subtitle"]]
+[[!template text="""1 small suggestion to me,""" start="00:01:10.520" video="qanda-test" id="subtitle"]]
+[[!template text="""should means optional,""" start="00:01:11.440" video="qanda-test" id="subtitle"]]
+[[!template text="""where shall or must means required.""" start="00:01:13.660" video="qanda-test" id="subtitle"]]
+[[!template text="""Not sure if it is too late to make a major""" start="00:01:15.940" video="qanda-test" id="subtitle"]]
+[[!template text="""grammar change like that.""" start="00:01:17.220" video="qanda-test" id="subtitle"]]
+[[!template text="""Very nice presentation.""" start="00:01:18.080" video="qanda-test" id="subtitle"]]
+[[!template text="""So thanks for presentation,""" start="00:01:19.840" video="qanda-test" id="subtitle"]]
+[[!template text="""but the package ERT, well,""" start="00:01:24.380" video="qanda-test" id="subtitle"]]
+[[!template text="""it's not something that we have come up with.""" start="00:01:27.920" video="qanda-test" id="subtitle"]]
+[[!template text="""It's a standard package.""" start="00:01:28.920" video="qanda-test" id="subtitle"]]
+[[!template text="""So I believe it has been around for a long""" start="00:01:32.320" video="qanda-test" id="subtitle"]]
+[[!template text="""time. So, but please feel free to make""" start="00:01:37.760" video="qanda-test" id="subtitle"]]
+[[!template text="""suggestions and maybe you can,""" start="00:01:39.680" video="qanda-test" id="subtitle"]]
+[[!template text="""you know, like do a copy or like an alias for""" start="00:01:43.660" video="qanda-test" id="subtitle"]]
+[[!template text="""that. If you believe it makes more sense for""" start="00:01:46.080" video="qanda-test" id="subtitle"]]
+[[!template text="""your test cases to have that instead.""" start="00:01:48.080" video="qanda-test" id="subtitle"]]
+[[!template text="""And then we have another question here.""" start="00:01:53.540" video="qanda-test" id="subtitle"]]
+[[!template text="""For your info, you may find this helpful for""" start="00:01:55.540" video="qanda-test" id="subtitle"]]
+[[!template text="""running MX test lint both from a command line""" start="00:01:58.780" video="qanda-test" id="subtitle"]]
+[[!template text="""and from within MX with a transit menu.""" start="00:02:01.220" video="qanda-test" id="subtitle"]]
+[[!template text="""GitHub alpha papa make sure,""" start="00:02:03.600" video="qanda-test" id="subtitle"]]
+[[!template text="""yes. It also works on remote CI.""" start="00:02:06.760" video="qanda-test" id="subtitle"]]
+[[!template text="""Yeah, thank you, Alpha Papa.""" start="00:02:08.240" video="qanda-test" id="subtitle"]]
+[[!template text="""I think I've looked into that,""" start="00:02:10.580" video="qanda-test" id="subtitle"]]
+[[!template text="""but we haven't made any use of that.""" start="00:02:13.440" video="qanda-test" id="subtitle"]]
+[[!template text="""But maybe you'll inspire me to give it""" start="00:02:17.920" video="qanda-test" id="subtitle"]]
+[[!template text="""another look.""" start="00:02:18.400" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: Hey guys.""" start="00:02:29.260" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: I remember, I recognize that voice.""" start="00:02:34.120" video="qanda-test" id="subtitle"]]
+[[!template text="""Hi, Bob. Hey, how are you?""" start="00:02:37.160" video="qanda-test" id="subtitle"]]
+[[!template text="""Congratulations, man. Thanks,""" start="00:02:40.240" video="qanda-test" id="subtitle"]]
+[[!template text="""Hugh. Thank you. I have another question""" start="00:02:43.020" video="qanda-test" id="subtitle"]]
+[[!template text="""here. It is easy to run ad hoc tests inside""" start="00:02:45.520" video="qanda-test" id="subtitle"]]
+[[!template text="""an Emacs session given the command line""" start="00:02:48.400" video="qanda-test" id="subtitle"]]
+[[!template text="""scripts you need to run to get the batch test""" start="00:02:51.180" video="qanda-test" id="subtitle"]]
+[[!template text="""session running? You said it's to run an""" start="00:02:54.960" video="qanda-test" id="subtitle"]]
+[[!template text="""ad-hoc test. I'm not sure I understand that""" start="00:03:05.680" video="qanda-test" id="subtitle"]]
+[[!template text="""question. Yes, please.""" start="00:03:14.440" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: Maybe I can rephrase. Sure.""" start="00:03:15.660" video="qanda-test" id="subtitle"]]
+[[!template text="""So I think what I understand is that since""" start="00:03:19.900" video="qanda-test" id="subtitle"]]
+[[!template text="""you have to use some of these command lines""" start="00:03:22.540" video="qanda-test" id="subtitle"]]
+[[!template text="""scripts to get a batch test session running,""" start="00:03:25.440" video="qanda-test" id="subtitle"]]
+[[!template text="""is it easy to run ad hoc tests in an Emacs""" start="00:03:28.780" video="qanda-test" id="subtitle"]]
+[[!template text="""session or does that, like in your""" start="00:03:30.700" video="qanda-test" id="subtitle"]]
+[[!template text="""experience, has that been difficult?""" start="00:03:32.040" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Well, from the command line,""" start="00:03:36.820" video="qanda-test" id="subtitle"]]
+[[!template text="""if you look at the command line,""" start="00:03:38.660" video="qanda-test" id="subtitle"]]
+[[!template text="""you'll see that it's only like a few image""" start="00:03:44.160" video="qanda-test" id="subtitle"]]
+[[!template text="""functions to call to get that behavior to run""" start="00:03:46.480" video="qanda-test" id="subtitle"]]
+[[!template text="""the batch tests. So I think we made some""" start="00:03:55.080" video="qanda-test" id="subtitle"]]
+[[!template text="""support function for that in hyperbole.""" start="00:03:57.100" video="qanda-test" id="subtitle"]]
+[[!template text="""So it's not, I don't think it's possible out""" start="00:04:02.800" video="qanda-test" id="subtitle"]]
+[[!template text="""of the box to do it, but it's not complicated""" start="00:04:05.540" video="qanda-test" id="subtitle"]]
+[[!template text="""to do it.""" start="00:04:08.060" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: You can define a test anytime,""" start="00:04:12.190" video="qanda-test" id="subtitle"]]
+[[!template text="""right? Just like a new function.""" start="00:04:14.780" video="qanda-test" id="subtitle"]]
+[[!template text="""So that's ad hoc. You just write your test""" start="00:04:18.899" video="qanda-test" id="subtitle"]]
+[[!template text="""and you can run it.""" start="00:04:20.019" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yeah, yeah, I mean, of course,""" start="00:04:22.900" video="qanda-test" id="subtitle"]]
+[[!template text="""but I got the impression it was about running""" start="00:04:25.900" video="qanda-test" id="subtitle"]]
+[[!template text="""all your tests like we did with the command""" start="00:04:28.620" video="qanda-test" id="subtitle"]]
+[[!template text="""line. Well, so the question is more about how""" start="00:04:35.740" video="qanda-test" id="subtitle"]]
+[[!template text="""would you run all your test cases from within""" start="00:04:38.260" video="qanda-test" id="subtitle"]]
+[[!template text="""Emacs? And the easy answer to that is""" start="00:04:44.860" video="qanda-test" id="subtitle"]]
+[[!template text="""actually you load all your test case files,""" start="00:04:48.420" video="qanda-test" id="subtitle"]]
+[[!template text="""and then you run ERT with the T as the test""" start="00:04:51.760" video="qanda-test" id="subtitle"]]
+[[!template text="""selector and then it will run all your test""" start="00:04:53.600" video="qanda-test" id="subtitle"]]
+[[!template text="""cases.""" start="00:04:53.880" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: Right. And I think they have expanded on""" start="00:05:01.780" video="qanda-test" id="subtitle"]]
+[[!template text="""their question a little bit as well,""" start="00:05:03.180" video="qanda-test" id="subtitle"]]
+[[!template text="""clarifying that. In other words,""" start="00:05:04.960" video="qanda-test" id="subtitle"]]
+[[!template text="""can you tweak tests in an Emacs session and""" start="00:05:07.200" video="qanda-test" id="subtitle"]]
+[[!template text="""run them right away? Which I believe,""" start="00:05:08.860" video="qanda-test" id="subtitle"]]
+[[!template text="""if I understand correctly what Bob was""" start="00:05:11.400" video="qanda-test" id="subtitle"]]
+[[!template text="""saying, you can basically define or redefine""" start="00:05:13.820" video="qanda-test" id="subtitle"]]
+[[!template text="""functions on the fly and then have them be""" start="00:05:15.920" video="qanda-test" id="subtitle"]]
+[[!template text="""run, right?""" start="00:05:16.440" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yes, yes. You just go into that test case and""" start="00:05:22.200" video="qanda-test" id="subtitle"]]
+[[!template text="""you just change it and you run it again.""" start="00:05:24.120" video="qanda-test" id="subtitle"]]
+[[!template text="""And either you have to sort of load it or you""" start="00:05:29.060" video="qanda-test" id="subtitle"]]
+[[!template text="""can use like the commercial thing I did.""" start="00:05:31.560" video="qanda-test" id="subtitle"]]
+[[!template text="""You use hyperbole and just hit meta return on""" start="00:05:36.140" video="qanda-test" id="subtitle"]]
+[[!template text="""the test case and it will load it and run the""" start="00:05:38.560" video="qanda-test" id="subtitle"]]
+[[!template text="""test case again. So that's of course what you""" start="00:05:42.240" video="qanda-test" id="subtitle"]]
+[[!template text="""normally do when you're defining a test or""" start="00:05:44.220" video="qanda-test" id="subtitle"]]
+[[!template text="""debug a test case or develop a test case.""" start="00:05:47.440" video="qanda-test" id="subtitle"]]
+[[!template text="""Just start with something small,""" start="00:05:49.960" video="qanda-test" id="subtitle"]]
+[[!template text="""just make sure maybe you can prepare the test""" start="00:05:52.700" video="qanda-test" id="subtitle"]]
+[[!template text="""properly and run it again and again and again""" start="00:05:55.320" video="qanda-test" id="subtitle"]]
+[[!template text="""until you're ready with it.""" start="00:05:56.720" video="qanda-test" id="subtitle"]]
+[[!template text="""That's a good point. You can definitely do""" start="00:05:59.760" video="qanda-test" id="subtitle"]]
+[[!template text="""that and that's part of how I normally""" start="00:06:02.800" video="qanda-test" id="subtitle"]]
+[[!template text="""develop the test cases that I mean start with""" start="00:06:06.420" video="qanda-test" id="subtitle"]]
+[[!template text="""something small so I can see that I get there""" start="00:06:09.160" video="qanda-test" id="subtitle"]]
+[[!template text="""maybe the right input in the buffer that I""" start="00:06:12.180" video="qanda-test" id="subtitle"]]
+[[!template text="""want to test on or something and I expand on""" start="00:06:14.180" video="qanda-test" id="subtitle"]]
+[[!template text="""that more and more and add more and more more""" start="00:06:18.160" video="qanda-test" id="subtitle"]]
+[[!template text="""and more more""" start="00:06:18.460" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: tests to it. You might tell them a bit about""" start="00:06:31.040" video="qanda-test" id="subtitle"]]
+[[!template text="""how many test cases you have.""" start="00:06:33.280" video="qanda-test" id="subtitle"]]
+[[!template text="""I guess you commented on that and like what""" start="00:06:36.020" video="qanda-test" id="subtitle"]]
+[[!template text="""happens, you know, with the CICD pipeline,""" start="00:06:40.320" video="qanda-test" id="subtitle"]]
+[[!template text="""every time we commit, you know,""" start="00:06:43.780" video="qanda-test" id="subtitle"]]
+[[!template text="""across all the versions and what you have set""" start="00:06:46.360" video="qanda-test" id="subtitle"]]
+[[!template text="""up there because you know I wish people could""" start="00:06:48.760" video="qanda-test" id="subtitle"]]
+[[!template text="""see it. You can go and check on GitHub and""" start="00:06:53.940" video="qanda-test" id="subtitle"]]
+[[!template text="""you can see the logs right of any of the""" start="00:06:57.440" video="qanda-test" id="subtitle"]]
+[[!template text="""builds and but tell them a bit about that""" start="00:06:59.760" video="qanda-test" id="subtitle"]]
+[[!template text="""Mats because I think that's pretty""" start="00:07:01.080" video="qanda-test" id="subtitle"]]
+[[!template text="""impressive.""" start="00:07:01.320" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Well, that's part of more the CI,""" start="00:07:07.280" video="qanda-test" id="subtitle"]]
+[[!template text="""CD, part of how we developed this using""" start="00:07:11.760" video="qanda-test" id="subtitle"]]
+[[!template text="""GitHub and workflows that you get out of the""" start="00:07:15.460" video="qanda-test" id="subtitle"]]
+[[!template text="""box from there. So this more than 300 test""" start="00:07:20.740" video="qanda-test" id="subtitle"]]
+[[!template text="""cases on our round for I think 5 different""" start="00:07:23.440" video="qanda-test" id="subtitle"]]
+[[!template text="""versions of Emacs when we do a pull request""" start="00:07:26.480" video="qanda-test" id="subtitle"]]
+[[!template text="""or a commit. So that's a good way to ensure""" start="00:07:33.900" video="qanda-test" id="subtitle"]]
+[[!template text="""that it works from version 27.2""" start="00:07:38.040" video="qanda-test" id="subtitle"]]
+[[!template text="""up to the latest master version because""" start="00:07:42.240" video="qanda-test" id="subtitle"]]
+[[!template text="""there's some changes in Emacs over different""" start="00:07:45.860" video="qanda-test" id="subtitle"]]
+[[!template text="""versions that can affect your functions or""" start="00:07:48.940" video="qanda-test" id="subtitle"]]
+[[!template text="""your code.""" start="00:07:49.600" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: They all run in parallel and so typically in""" start="00:07:56.580" video="qanda-test" id="subtitle"]]
+[[!template text="""under 60 seconds I think you've got all of""" start="00:08:00.580" video="qanda-test" id="subtitle"]]
+[[!template text="""them run so you've got pretty extensive""" start="00:08:03.960" video="qanda-test" id="subtitle"]]
+[[!template text="""testing which does catch interesting bugs""" start="00:08:08.860" video="qanda-test" id="subtitle"]]
+[[!template text="""here and there, right?""" start="00:08:09.760" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yes, of course it does.""" start="00:08:13.320" video="qanda-test" id="subtitle"]]
+[[!template text="""I mean, you normally develop with 1 version""" start="00:08:18.060" video="qanda-test" id="subtitle"]]
+[[!template text="""and then you think everything is okay.""" start="00:08:20.280" video="qanda-test" id="subtitle"]]
+[[!template text="""But then when you're tested with the""" start="00:08:21.720" video="qanda-test" id="subtitle"]]
+[[!template text="""different versions, you find out that there""" start="00:08:23.460" video="qanda-test" id="subtitle"]]
+[[!template text="""are some changes and there are things you""" start="00:08:26.080" video="qanda-test" id="subtitle"]]
+[[!template text="""might not sort of keep track of what's""" start="00:08:30.140" video="qanda-test" id="subtitle"]]
+[[!template text="""happening also. So that's a way to get""" start="00:08:34.340" video="qanda-test" id="subtitle"]]
+[[!template text="""noticed that the core developers of Emacs""" start="00:08:38.559" video="qanda-test" id="subtitle"]]
+[[!template text="""have changed something that you sort of based""" start="00:08:41.120" video="qanda-test" id="subtitle"]]
+[[!template text="""your code on. Now I got another question""" start="00:08:44.380" video="qanda-test" id="subtitle"]]
+[[!template text="""here. Did you have to change hyperbole code""" start="00:08:47.900" video="qanda-test" id="subtitle"]]
+[[!template text="""and design to be more readily testable as you""" start="00:08:50.580" video="qanda-test" id="subtitle"]]
+[[!template text="""were increasing your test coverage?""" start="00:08:52.160" video="qanda-test" id="subtitle"]]
+[[!template text="""Well, we haven't done that to a lot,""" start="00:08:55.520" video="qanda-test" id="subtitle"]]
+[[!template text="""to a big degree, although I believe that that""" start="00:09:00.160" video="qanda-test" id="subtitle"]]
+[[!template text="""is an important thing for sort of the future""" start="00:09:03.760" video="qanda-test" id="subtitle"]]
+[[!template text="""to do that because some of the hyperbolic""" start="00:09:06.020" video="qanda-test" id="subtitle"]]
+[[!template text="""functions are very complicated and long and""" start="00:09:08.520" video="qanda-test" id="subtitle"]]
+[[!template text="""that makes testing them rather difficult.""" start="00:09:10.640" video="qanda-test" id="subtitle"]]
+[[!template text="""So, at a few places we have sort of broken up""" start="00:09:14.660" video="qanda-test" id="subtitle"]]
+[[!template text="""functions in smaller pieces so it'd be easier""" start="00:09:17.260" video="qanda-test" id="subtitle"]]
+[[!template text="""to do like unit tests of the different parts""" start="00:09:20.280" video="qanda-test" id="subtitle"]]
+[[!template text="""of it. But there's a lot of more work that""" start="00:09:27.740" video="qanda-test" id="subtitle"]]
+[[!template text="""has to be done there.""" start="00:09:28.680" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: 1 of the nice things is you know the great""" start="00:09:33.820" video="qanda-test" id="subtitle"]]
+[[!template text="""environment in Lisp where we're able to do a""" start="00:09:36.760" video="qanda-test" id="subtitle"]]
+[[!template text="""lot of interactive bottom-up testing before""" start="00:09:40.520" video="qanda-test" id="subtitle"]]
+[[!template text="""we even get to lighting tech pieces.""" start="00:09:42.840" video="qanda-test" id="subtitle"]]
+[[!template text="""So it does tend to be more higher level bugs,""" start="00:09:48.740" video="qanda-test" id="subtitle"]]
+[[!template text="""I think, that get caught in cross-functional""" start="00:09:51.140" video="qanda-test" id="subtitle"]]
+[[!template text="""interaction. We had 1 recently that was an""" start="00:09:55.940" video="qanda-test" id="subtitle"]]
+[[!template text="""Emacs version change. It had been a function""" start="00:09:58.100" video="qanda-test" id="subtitle"]]
+[[!template text="""that had existed for a long time.""" start="00:10:01.100" video="qanda-test" id="subtitle"]]
+[[!template text="""It had an and rest in it,""" start="00:10:03.340" video="qanda-test" id="subtitle"]]
+[[!template text="""in its argument list, so it would assemble""" start="00:10:05.740" video="qanda-test" id="subtitle"]]
+[[!template text="""the list of arguments from individual""" start="00:10:08.600" video="qanda-test" id="subtitle"]]
+[[!template text="""arguments that you would give it,""" start="00:10:10.320" video="qanda-test" id="subtitle"]]
+[[!template text="""and they decided in a recent version,""" start="00:10:13.100" video="qanda-test" id="subtitle"]]
+[[!template text="""I think with Stefan's input,""" start="00:10:15.200" video="qanda-test" id="subtitle"]]
+[[!template text="""to change that to a list and allow the prior""" start="00:10:19.400" video="qanda-test" id="subtitle"]]
+[[!template text="""behavior, but it would issue a warning if you""" start="00:10:22.740" video="qanda-test" id="subtitle"]]
+[[!template text="""use the prior behavior.""" start="00:10:23.620" video="qanda-test" id="subtitle"]]
+[[!template text="""So all of a sudden, the way you were supposed""" start="00:10:25.560" video="qanda-test" id="subtitle"]]
+[[!template text="""to do it became semi-invalid.""" start="00:10:27.180" video="qanda-test" id="subtitle"]]
+[[!template text="""And so we started getting the warning,""" start="00:10:30.440" video="qanda-test" id="subtitle"]]
+[[!template text="""and we've tried to eliminate all those""" start="00:10:32.760" video="qanda-test" id="subtitle"]]
+[[!template text="""warnings in recent hyperbole developments.""" start="00:10:35.600" video="qanda-test" id="subtitle"]]
+[[!template text="""So we're like, what do we do?""" start="00:10:37.120" video="qanda-test" id="subtitle"]]
+[[!template text="""You know, because we wanted to be backward""" start="00:10:39.020" video="qanda-test" id="subtitle"]]
+[[!template text="""compatible to where you couldn't use a list.""" start="00:10:42.140" video="qanda-test" id="subtitle"]]
+[[!template text="""It required you to use individual arguments.""" start="00:10:44.620" video="qanda-test" id="subtitle"]]
+[[!template text="""And now it's sort of requiring you to do""" start="00:10:48.380" video="qanda-test" id="subtitle"]]
+[[!template text="""that. And all of that was caused by the""" start="00:10:51.660" video="qanda-test" id="subtitle"]]
+[[!template text="""automatic testing on it.""" start="00:10:52.940" video="qanda-test" id="subtitle"]]
+[[!template text="""So you said, Max, you were going to tell us""" start="00:11:08.680" video="qanda-test" id="subtitle"]]
+[[!template text="""what you learned. So what are the major""" start="00:11:12.740" video="qanda-test" id="subtitle"]]
+[[!template text="""things that you learned in doing all of this""" start="00:11:15.368" video="qanda-test" id="subtitle"]]
+[[!template text="""work? All of this work?""" start="00:11:15.680" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Well, I tried to cover some of it in the""" start="00:11:26.520" video="qanda-test" id="subtitle"]]
+[[!template text="""presentation, but as I was going along,""" start="00:11:29.380" video="qanda-test" id="subtitle"]]
+[[!template text="""the presentation became like twice as long as""" start="00:11:33.420" video="qanda-test" id="subtitle"]]
+[[!template text="""fitted into the time we had so I had to cut""" start="00:11:36.180" video="qanda-test" id="subtitle"]]
+[[!template text="""it out. But I think some of the core things""" start="00:11:42.380" video="qanda-test" id="subtitle"]]
+[[!template text="""still is in the presentation.""" start="00:11:44.340" video="qanda-test" id="subtitle"]]
+[[!template text="""From a personal perspective,""" start="00:11:49.560" video="qanda-test" id="subtitle"]]
+[[!template text="""And this might not be hard to realize,""" start="00:11:52.440" video="qanda-test" id="subtitle"]]
+[[!template text="""but forcing yourself to test functions,""" start="00:11:56.960" video="qanda-test" id="subtitle"]]
+[[!template text="""test code really forces you to understand the""" start="00:12:02.900" video="qanda-test" id="subtitle"]]
+[[!template text="""code a little bit better in a way that sort""" start="00:12:05.080" video="qanda-test" id="subtitle"]]
+[[!template text="""of makes it easier than just to read the""" start="00:12:07.300" video="qanda-test" id="subtitle"]]
+[[!template text="""code. I don't know how it is for the rest""" start="00:12:11.460" video="qanda-test" id="subtitle"]]
+[[!template text="""listening to this, but for me it works so""" start="00:12:13.780" video="qanda-test" id="subtitle"]]
+[[!template text="""that if I just read the code then I don't""" start="00:12:16.580" video="qanda-test" id="subtitle"]]
+[[!template text="""sort of become as sharp as I should be but if""" start="00:12:20.140" video="qanda-test" id="subtitle"]]
+[[!template text="""I try to write the test case for it then I""" start="00:12:22.500" video="qanda-test" id="subtitle"]]
+[[!template text="""really need to understand better of all the""" start="00:12:24.680" video="qanda-test" id="subtitle"]]
+[[!template text="""edge cases and all the sort of states and etc""" start="00:12:27.660" video="qanda-test" id="subtitle"]]
+[[!template text="""that is involved and I think that's That's""" start="00:12:30.060" video="qanda-test" id="subtitle"]]
+[[!template text="""what's sort of 1 of the learning things I""" start="00:12:33.080" video="qanda-test" id="subtitle"]]
+[[!template text="""wanted to communicate as well that I don't""" start="00:12:34.960" video="qanda-test" id="subtitle"]]
+[[!template text="""think I covered in detail in the""" start="00:12:38.940" video="qanda-test" id="subtitle"]]
+[[!template text="""presentation. Maybe all this,""" start="00:12:41.480" video="qanda-test" id="subtitle"]]
+[[!template text="""but try it. 1 other sort of more from the fun""" start="00:12:48.060" video="qanda-test" id="subtitle"]]
+[[!template text="""side is that I really think it's fun to write""" start="00:12:50.740" video="qanda-test" id="subtitle"]]
+[[!template text="""the test. So if you haven't tests in your""" start="00:12:55.080" video="qanda-test" id="subtitle"]]
+[[!template text="""package, you should start doing that because""" start="00:12:58.020" video="qanda-test" id="subtitle"]]
+[[!template text="""it is fun. It might feel like some extra""" start="00:13:05.740" video="qanda-test" id="subtitle"]]
+[[!template text="""work, but it really pays off in the long run,""" start="00:13:08.080" video="qanda-test" id="subtitle"]]
+[[!template text="""especially if you have it in like a pipeline""" start="00:13:10.320" video="qanda-test" id="subtitle"]]
+[[!template text="""and where you can run it regularly when you""" start="00:13:12.520" video="qanda-test" id="subtitle"]]
+[[!template text="""do new commits, et cetera.""" start="00:13:13.940" video="qanda-test" id="subtitle"]]
+[[!template text="""So, I mean, that's maybe obvious from,""" start="00:13:16.560" video="qanda-test" id="subtitle"]]
+[[!template text="""if you look from the commercial side or your""" start="00:13:19.160" video="qanda-test" id="subtitle"]]
+[[!template text="""work side to do it like that.""" start="00:13:21.080" video="qanda-test" id="subtitle"]]
+[[!template text="""But even for your hobby project,""" start="00:13:22.260" video="qanda-test" id="subtitle"]]
+[[!template text="""it can be very sort of pay off really well.""" start="00:13:26.260" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: It's worked really well when we're adding new""" start="00:13:32.900" video="qanda-test" id="subtitle"]]
+[[!template text="""functionality or we're changing some of the""" start="00:13:35.020" video="qanda-test" id="subtitle"]]
+[[!template text="""plumbing in the system.""" start="00:13:36.560" video="qanda-test" id="subtitle"]]
+[[!template text="""You know, you go and you do some surgery and""" start="00:13:40.400" video="qanda-test" id="subtitle"]]
+[[!template text="""then you run the tests.""" start="00:13:41.320" video="qanda-test" id="subtitle"]]
+[[!template text="""And sometimes 6 to 10 tests will fail.""" start="00:13:45.400" video="qanda-test" id="subtitle"]]
+[[!template text="""And you find there, you know,""" start="00:13:48.260" video="qanda-test" id="subtitle"]]
+[[!template text="""it tends to be they're all interconnected and""" start="00:13:50.460" video="qanda-test" id="subtitle"]]
+[[!template text="""it leads you back to the single source.""" start="00:13:52.920" video="qanda-test" id="subtitle"]]
+[[!template text="""You fix that and you know it could be an edge""" start="00:13:56.660" video="qanda-test" id="subtitle"]]
+[[!template text="""case and off by 1 or Sometimes it's an""" start="00:14:00.560" video="qanda-test" id="subtitle"]]
+[[!template text="""assumption about the way something is used""" start="00:14:03.520" video="qanda-test" id="subtitle"]]
+[[!template text="""and it's not actually always true.""" start="00:14:05.980" video="qanda-test" id="subtitle"]]
+[[!template text="""And so, Matt's just really good at""" start="00:14:09.520" video="qanda-test" id="subtitle"]]
+[[!template text="""identifying some of those scenarios and""" start="00:14:13.540" video="qanda-test" id="subtitle"]]
+[[!template text="""keeping us honest, I guess I would say.""" start="00:14:17.480" video="qanda-test" id="subtitle"]]
+[[!template text="""So I love, I run it as much as I before,""" start="00:14:22.900" video="qanda-test" id="subtitle"]]
+[[!template text="""you know, even before I commit something.""" start="00:14:26.400" video="qanda-test" id="subtitle"]]
+[[!template text="""So I get to see, you know,""" start="00:14:29.960" video="qanda-test" id="subtitle"]]
+[[!template text="""if anything has progressed.""" start="00:14:30.940" video="qanda-test" id="subtitle"]]
+[[!template text="""So yeah, I really recommend this process to""" start="00:14:39.480" video="qanda-test" id="subtitle"]]
+[[!template text="""people. I haven't seen it done.""" start="00:14:42.120" video="qanda-test" id="subtitle"]]
+[[!template text="""I don't think that, I don't know any other""" start="00:14:45.720" video="qanda-test" id="subtitle"]]
+[[!template text="""package that has done it to this level.""" start="00:14:47.800" video="qanda-test" id="subtitle"]]
+[[!template text="""And it's been working really great for us.""" start="00:14:51.560" video="qanda-test" id="subtitle"]]
+[[!template text="""And I think, well, we'll see too when we""" start="00:14:55.440" video="qanda-test" id="subtitle"]]
+[[!template text="""release to the general public.""" start="00:14:56.780" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: But Bob, also, maybe the test part of""" start="00:15:04.380" video="qanda-test" id="subtitle"]]
+[[!template text="""different packages is not the first thing you""" start="00:15:06.400" video="qanda-test" id="subtitle"]]
+[[!template text="""look at. So I know there are packages that""" start="00:15:08.900" video="qanda-test" id="subtitle"]]
+[[!template text="""have testing, a lot of testing,""" start="00:15:10.960" video="qanda-test" id="subtitle"]]
+[[!template text="""but how much, much testing they have or not,""" start="00:15:13.860" video="qanda-test" id="subtitle"]]
+[[!template text="""I don't know. It's not what you normally look""" start="00:15:16.060" video="qanda-test" id="subtitle"]]
+[[!template text="""into when you look at someone's else code.""" start="00:15:17.900" video="qanda-test" id="subtitle"]]
+[[!template text="""You look maybe on the functionality side but""" start="00:15:20.600" video="qanda-test" id="subtitle"]]
+[[!template text="""not on how they've done the sort of the""" start="00:15:22.760" video="qanda-test" id="subtitle"]]
+[[!template text="""quality side. So there could be other""" start="00:15:26.540" video="qanda-test" id="subtitle"]]
+[[!template text="""packages out there that are well equipped.""" start="00:15:28.780" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: I hope so. I hope so.""" start="00:15:31.800" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: What's the craziest bug you found when""" start="00:15:39.860" video="qanda-test" id="subtitle"]]
+[[!template text="""writing these tests? Well,""" start="00:15:44.700" video="qanda-test" id="subtitle"]]
+[[!template text="""What springs to my mind just now is that we""" start="00:15:50.760" video="qanda-test" id="subtitle"]]
+[[!template text="""were doing some tests or I would do some""" start="00:15:52.760" video="qanda-test" id="subtitle"]]
+[[!template text="""tests for when you narrow,""" start="00:15:55.920" video="qanda-test" id="subtitle"]]
+[[!template text="""what do you say that? When you,""" start="00:15:57.940" video="qanda-test" id="subtitle"]]
+[[!template text="""in outlining, when you sort of compress""" start="00:16:04.500" video="qanda-test" id="subtitle"]]
+[[!template text="""things in an outline, so you just,""" start="00:16:06.480" video="qanda-test" id="subtitle"]]
+[[!template text="""sorry Bob, maybe you have it,""" start="00:16:08.540" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: When you hide text.""" start="00:16:12.100" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: What I'm looking for? Yeah,""" start="00:16:12.740" video="qanda-test" id="subtitle"]]
+[[!template text="""when you hide. So I was doing some cursor""" start="00:16:15.580" video="qanda-test" id="subtitle"]]
+[[!template text="""movement over that. And I always assume that""" start="00:16:17.780" video="qanda-test" id="subtitle"]]
+[[!template text="""if you do like a prefix argument to like a""" start="00:16:22.540" video="qanda-test" id="subtitle"]]
+[[!template text="""simple cursor movement,""" start="00:16:23.800" video="qanda-test" id="subtitle"]]
+[[!template text="""like control F moving 1 character position,""" start="00:16:26.420" video="qanda-test" id="subtitle"]]
+[[!template text="""and you would give it the,""" start="00:16:28.340" video="qanda-test" id="subtitle"]]
+[[!template text="""and then the prefix, like you want to move""" start="00:16:36.580" video="qanda-test" id="subtitle"]]
+[[!template text="""like 2 or 3 positions,""" start="00:16:39.140" video="qanda-test" id="subtitle"]]
+[[!template text="""you would do like control U 3 and then""" start="00:16:43.040" video="qanda-test" id="subtitle"]]
+[[!template text="""control F and you move 3.""" start="00:16:44.240" video="qanda-test" id="subtitle"]]
+[[!template text="""I always assumed that that would be exactly""" start="00:16:46.560" video="qanda-test" id="subtitle"]]
+[[!template text="""the same as if you just hit the key control F""" start="00:16:49.240" video="qanda-test" id="subtitle"]]
+[[!template text="""3 times, but it's not.""" start="00:16:50.740" video="qanda-test" id="subtitle"]]
+[[!template text="""So it's not the bug, it's a feature,""" start="00:16:53.160" video="qanda-test" id="subtitle"]]
+[[!template text="""but that was the craziest thing.""" start="00:16:54.620" video="qanda-test" id="subtitle"]]
+[[!template text="""I spent the night trying to figure out why""" start="00:16:58.180" video="qanda-test" id="subtitle"]]
+[[!template text="""our code was wrong, but It turns out that's""" start="00:17:00.720" video="qanda-test" id="subtitle"]]
+[[!template text="""how Emacs behaves. Try it out yourself.""" start="00:17:03.560" video="qanda-test" id="subtitle"]]
+[[!template text="""Try to move over the 3 dots at the end of""" start="00:17:07.920" video="qanda-test" id="subtitle"]]
+[[!template text="""that and see what happens.""" start="00:17:09.140" video="qanda-test" id="subtitle"]]
+[[!template text="""Do it with cursor hitting the key or using a""" start="00:17:14.060" video="qanda-test" id="subtitle"]]
+[[!template text="""prefix argument and you see it behaves""" start="00:17:16.260" video="qanda-test" id="subtitle"]]
+[[!template text="""differently. That was the craziest thing.""" start="00:17:18.720" video="qanda-test" id="subtitle"]]
+[[!template text="""I think there was some other crazy thing or""" start="00:17:21.960" video="qanda-test" id="subtitle"]]
+[[!template text="""deep learning also, but I can't come up with""" start="00:17:24.280" video="qanda-test" id="subtitle"]]
+[[!template text="""it at the moment. So maybe I can write it in""" start="00:17:26.599" video="qanda-test" id="subtitle"]]
+[[!template text="""the Q&A later.""" start="00:17:27.900" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: I think we're out of time on the stream,""" start="00:17:31.200" video="qanda-test" id="subtitle"]]
+[[!template text="""but people are welcome to join Mats and Bob""" start="00:17:33.360" video="qanda-test" id="subtitle"]]
+[[!template text="""here on BigBlueButton to further discuss""" start="00:17:35.280" video="qanda-test" id="subtitle"]]
+[[!template text="""this. Thank you both.""" start="00:17:36.480" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Okay, thank you. Thanks,""" start="00:17:38.674" video="qanda-test" id="subtitle"]]
+[[!template text="""Makaay. Thank you. I don't know,""" start="00:17:46.100" video="qanda-test" id="subtitle"]]
+[[!template text="""Is it only me and Bob here?""" start="00:17:48.740" video="qanda-test" id="subtitle"]]
+[[!template text="""So Bob, do you want to say something?""" start="00:17:50.680" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 2]: Well, I think it's been a great day.""" start="00:17:57.440" video="qanda-test" id="subtitle"]]
+[[!template text="""And I'm glad we did this.""" start="00:18:00.720" video="qanda-test" id="subtitle"]]
+[[!template text="""It takes a lot of energy.""" start="00:18:02.280" video="qanda-test" id="subtitle"]]
+[[!template text="""I'm just really excited about the progress""" start="00:18:15.140" video="qanda-test" id="subtitle"]]
+[[!template text="""that this, and we're actually doing a lot of""" start="00:18:20.580" video="qanda-test" id="subtitle"]]
+[[!template text="""QA at work and my professional software work""" start="00:18:23.940" video="qanda-test" id="subtitle"]]
+[[!template text="""and looking at you know how we can do more""" start="00:18:28.500" video="qanda-test" id="subtitle"]]
+[[!template text="""test driven development and so everybody's""" start="00:18:32.980" video="qanda-test" id="subtitle"]]
+[[!template text="""talking about this you know we've got AI over""" start="00:18:35.980" video="qanda-test" id="subtitle"]]
+[[!template text="""here that can generate test cases.""" start="00:18:37.540" video="qanda-test" id="subtitle"]]
+[[!template text="""But, you know, strangely enough,""" start="00:18:40.200" video="qanda-test" id="subtitle"]]
+[[!template text="""with the rapidity of development and web""" start="00:18:43.100" video="qanda-test" id="subtitle"]]
+[[!template text="""applications, I think the level of testing""" start="00:18:46.720" video="qanda-test" id="subtitle"]]
+[[!template text="""has gone down in recent years compared to""" start="00:18:50.140" video="qanda-test" id="subtitle"]]
+[[!template text="""where it used to be, right?""" start="00:18:51.500" video="qanda-test" id="subtitle"]]
+[[!template text="""Because the pace has gone up.""" start="00:18:53.040" video="qanda-test" id="subtitle"]]
+[[!template text="""And so I think it's starting to turn again""" start="00:18:57.340" video="qanda-test" id="subtitle"]]
+[[!template text="""where people are saying,""" start="00:18:58.740" video="qanda-test" id="subtitle"]]
+[[!template text="""we can't just release crap into the""" start="00:19:01.940" video="qanda-test" id="subtitle"]]
+[[!template text="""Webisphere and we have to better ourselves.""" start="00:19:08.120" video="qanda-test" id="subtitle"]]
+[[!template text="""And with all these advanced tool sets that""" start="00:19:13.620" video="qanda-test" id="subtitle"]]
+[[!template text="""you have, that you can do CICD testing,""" start="00:19:16.100" video="qanda-test" id="subtitle"]]
+[[!template text="""you know, I just, I just see it coming""" start="00:19:19.860" video="qanda-test" id="subtitle"]]
+[[!template text="""around, you know, as people develop new""" start="00:19:21.900" video="qanda-test" id="subtitle"]]
+[[!template text="""things. So That's kind of exciting to me""" start="00:19:24.000" video="qanda-test" id="subtitle"]]
+[[!template text="""because I came from a manufacturing culture""" start="00:19:26.980" video="qanda-test" id="subtitle"]]
+[[!template text="""originally where we, our company actually""" start="00:19:30.300" video="qanda-test" id="subtitle"]]
+[[!template text="""started a lot of the manufacturing quality""" start="00:19:33.800" video="qanda-test" id="subtitle"]]
+[[!template text="""efforts that you saw in Japan and elsewhere""" start="00:19:37.420" video="qanda-test" id="subtitle"]]
+[[!template text="""in America for a long time and that was you""" start="00:19:40.600" video="qanda-test" id="subtitle"]]
+[[!template text="""know entirely through testing.""" start="00:19:42.040" video="qanda-test" id="subtitle"]]
+[[!template text="""We used to just build incredible test cases""" start="00:19:46.640" video="qanda-test" id="subtitle"]]
+[[!template text="""because we were combining software with""" start="00:19:49.120" video="qanda-test" id="subtitle"]]
+[[!template text="""hardware. And if, you know,""" start="00:19:51.100" video="qanda-test" id="subtitle"]]
+[[!template text="""the hardware doesn't work and you ship a""" start="00:19:53.460" video="qanda-test" id="subtitle"]]
+[[!template text="""million units, you're,""" start="00:19:55.080" video="qanda-test" id="subtitle"]]
+[[!template text="""you're in trouble. So,""" start="00:19:57.340" video="qanda-test" id="subtitle"]]
+[[!template text="""that was just something we had to do.""" start="00:20:00.260" video="qanda-test" id="subtitle"]]
+[[!template text="""And so it's nice to start to see that curve""" start="00:20:04.280" video="qanda-test" id="subtitle"]]
+[[!template text="""come around. And I think,""" start="00:20:07.020" video="qanda-test" id="subtitle"]]
+[[!template text="""you know, Matt Vance is very modest,""" start="00:20:10.380" video="qanda-test" id="subtitle"]]
+[[!template text="""but I think he's really the 1 that started us""" start="00:20:16.680" video="qanda-test" id="subtitle"]]
+[[!template text="""down this path and really made it into a""" start="00:20:20.400" video="qanda-test" id="subtitle"]]
+[[!template text="""reality. So everybody else just gets to""" start="00:20:24.620" video="qanda-test" id="subtitle"]]
+[[!template text="""benefit from that work.""" start="00:20:25.760" video="qanda-test" id="subtitle"]]
+[[!template text="""So thanks.""" start="00:20:27.540" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: That's awesome.""" start="00:20:32.760" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Thanks. Okay. Yeah. So if there's nothing""" start="00:20:39.960" video="qanda-test" id="subtitle"]]
+[[!template text="""more here, then maybe we should just close""" start="00:20:43.200" video="qanda-test" id="subtitle"]]
+[[!template text="""this and I go over to write in the etherpad""" start="00:20:45.440" video="qanda-test" id="subtitle"]]
+[[!template text="""the replies we had.""" start="00:20:47.960" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: Right, yeah, I think, let's see,""" start="00:20:51.900" video="qanda-test" id="subtitle"]]
+[[!template text="""I see 1 other person here,""" start="00:20:53.520" video="qanda-test" id="subtitle"]]
+[[!template text="""I believe Ihor just joined us.""" start="00:20:55.080" video="qanda-test" id="subtitle"]]
+[[!template text="""Yeah. Yeah, so if you do want to discuss with""" start="00:20:58.780" video="qanda-test" id="subtitle"]]
+[[!template text="""Mats and Bob, you're welcome to,""" start="00:21:00.220" video="qanda-test" id="subtitle"]]
+[[!template text="""otherwise, yeah, we can close the room now.""" start="00:21:02.200" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: Well, I think I missed most of the talk""" start="00:21:05.800" video="qanda-test" id="subtitle"]]
+[[!template text="""because I had power outage,""" start="00:21:06.900" video="qanda-test" id="subtitle"]]
+[[!template text="""but the part I heard was about the mock""" start="00:21:12.180" video="qanda-test" id="subtitle"]]
+[[!template text="""library. And you mentioned that you don't""" start="00:21:16.860" video="qanda-test" id="subtitle"]]
+[[!template text="""like CL-let, but instead you use mock.""" start="00:21:20.200" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yeah, I was more saying that you have to do a""" start="00:21:29.700" video="qanda-test" id="subtitle"]]
+[[!template text="""lot more work when you use the CL letdef.""" start="00:21:31.560" video="qanda-test" id="subtitle"]]
+[[!template text="""It's for more ambitious and maybe more""" start="00:21:34.540" video="qanda-test" id="subtitle"]]
+[[!template text="""complicated cases where you want to really""" start="00:21:37.000" video="qanda-test" id="subtitle"]]
+[[!template text="""make a new implementation,""" start="00:21:38.840" video="qanda-test" id="subtitle"]]
+[[!template text="""test implementation. If you use the mock,""" start="00:21:41.940" video="qanda-test" id="subtitle"]]
+[[!template text="""you get a lot of things out of the box,""" start="00:21:44.380" video="qanda-test" id="subtitle"]]
+[[!template text="""verifying that you actually,""" start="00:21:47.440" video="qanda-test" id="subtitle"]]
+[[!template text="""like the mock was actually called for""" start="00:21:50.820" video="qanda-test" id="subtitle"]]
+[[!template text="""instance, whereas if you do with the CLLatf,""" start="00:21:53.320" video="qanda-test" id="subtitle"]]
+[[!template text="""you would have to take correct track of that""" start="00:21:56.520" video="qanda-test" id="subtitle"]]
+[[!template text="""yourself. And so, so a lot of more work.""" start="00:22:02.020" video="qanda-test" id="subtitle"]]
+[[!template text="""Oh yeah.""" start="00:22:03.760" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: I'm saying that most of the time CLLess is""" start="00:22:07.940" video="qanda-test" id="subtitle"]]
+[[!template text="""used for simple cases actually.""" start="00:22:09.720" video="qanda-test" id="subtitle"]]
+[[!template text="""Because, just for example,""" start="00:22:12.320" video="qanda-test" id="subtitle"]]
+[[!template text="""the function always returns the same.""" start="00:22:15.100" video="qanda-test" id="subtitle"]]
+[[!template text="""And it tends to be simple lambda that ignores""" start="00:22:17.980" video="qanda-test" id="subtitle"]]
+[[!template text="""all the input arguments.""" start="00:22:19.040" video="qanda-test" id="subtitle"]]
+[[!template text="""So that's really trivial most of the time but""" start="00:22:23.000" video="qanda-test" id="subtitle"]]
+[[!template text="""I actually thought the opposite that mock is""" start="00:22:25.520" video="qanda-test" id="subtitle"]]
+[[!template text="""supposed to be used for non-trivial cases.""" start="00:22:27.640" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Sorry, what was the question?""" start="00:22:32.280" video="qanda-test" id="subtitle"]]
+[[!template text="""Mock was supposed to be used for non-trivial.""" start="00:22:35.280" video="qanda-test" id="subtitle"]]
+[[!template text="""Yeah I mean I don't know how to explain this.""" start="00:22:47.680" video="qanda-test" id="subtitle"]]
+[[!template text="""I mean, CLF can be used for non-trivial""" start="00:22:50.140" video="qanda-test" id="subtitle"]]
+[[!template text="""definitely. You can define then any behavior""" start="00:22:54.400" video="qanda-test" id="subtitle"]]
+[[!template text="""you want. You can write your own function,""" start="00:22:56.180" video="qanda-test" id="subtitle"]]
+[[!template text="""but you need to keep track of whether that""" start="00:22:58.440" video="qanda-test" id="subtitle"]]
+[[!template text="""function is called or not,""" start="00:22:59.620" video="qanda-test" id="subtitle"]]
+[[!template text="""for instance. So you have to make note of""" start="00:23:06.260" video="qanda-test" id="subtitle"]]
+[[!template text="""that the function was called so you can fire""" start="00:23:08.440" video="qanda-test" id="subtitle"]]
+[[!template text="""sort of an error in case your function wasn't""" start="00:23:12.440" video="qanda-test" id="subtitle"]]
+[[!template text="""called because that would be 1 error case.""" start="00:23:16.960" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: So you mean the mock fires an error if the""" start="00:23:20.660" video="qanda-test" id="subtitle"]]
+[[!template text="""mocked function was actually not called?""" start="00:23:22.580" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yes, it does. Yes. So if your assumptions,""" start="00:23:30.060" video="qanda-test" id="subtitle"]]
+[[!template text="""you sort of document with the mock also your""" start="00:23:33.900" video="qanda-test" id="subtitle"]]
+[[!template text="""assumptions how your code is going to be""" start="00:23:37.080" video="qanda-test" id="subtitle"]]
+[[!template text="""called. And if those are wrong,""" start="00:23:40.020" video="qanda-test" id="subtitle"]]
+[[!template text="""you will get an error.""" start="00:23:41.120" video="qanda-test" id="subtitle"]]
+[[!template text="""So you would, so if the implementation would""" start="00:23:43.680" video="qanda-test" id="subtitle"]]
+[[!template text="""maybe change, for instance,""" start="00:23:44.840" video="qanda-test" id="subtitle"]]
+[[!template text="""and not call the thing you're mocking,""" start="00:23:46.640" video="qanda-test" id="subtitle"]]
+[[!template text="""then you will notice that.""" start="00:23:50.460" video="qanda-test" id="subtitle"]]
+[[!template text="""But if you see a letdef,""" start="00:23:53.100" video="qanda-test" id="subtitle"]]
+[[!template text="""then you will have to keep track of that""" start="00:23:54.840" video="qanda-test" id="subtitle"]]
+[[!template text="""yourself. Okay, I see.""" start="00:23:57.560" video="qanda-test" id="subtitle"]]
+[[!template text="""I see.""" start="00:23:58.260" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: And you know, our mode also uses a lot of""" start="00:24:01.240" video="qanda-test" id="subtitle"]]
+[[!template text="""test. In our mode, we have a lot of tests""" start="00:24:09.340" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Ah, okay. Yeah. Yeah. I'm sure I have.""" start="00:24:13.940" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: also. We rely on CLLatF for,""" start="00:24:15.900" video="qanda-test" id="subtitle"]]
+[[!template text="""we don't use third-party libraries at all.""" start="00:24:19.220" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: Oh, you use CLLatF, okay.""" start="00:24:22.140" video="qanda-test" id="subtitle"]]
+[[!template text="""Yeah. Yeah. Yeah. At First I found it very""" start="00:24:26.680" video="qanda-test" id="subtitle"]]
+[[!template text="""powerful to use that, but then I sort of,""" start="00:24:29.480" video="qanda-test" id="subtitle"]]
+[[!template text="""I learned more about how we can use the""" start="00:24:32.120" video="qanda-test" id="subtitle"]]
+[[!template text="""mocking library for what I needed.""" start="00:24:34.340" video="qanda-test" id="subtitle"]]
+[[!template text="""And I prefer that at the moment.""" start="00:24:36.900" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: I see, that is interesting.""" start="00:24:40.560" video="qanda-test" id="subtitle"]]
+[[!template text="""Because I had seen it,""" start="00:24:42.500" video="qanda-test" id="subtitle"]]
+[[!template text="""but I didn't consider that it's gonna be""" start="00:24:45.440" video="qanda-test" id="subtitle"]]
+[[!template text="""useful even in simple cases.""" start="00:24:46.800" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: It has its limitations.""" start="00:24:52.640" video="qanda-test" id="subtitle"]]
+[[!template text="""So it's like life, how you turn depends.""" start="00:24:58.260" video="qanda-test" id="subtitle"]]
+[[!template text="""But maybe I should look more into the org""" start="00:25:03.740" video="qanda-test" id="subtitle"]]
+[[!template text="""mode and the test case to learn more about""" start="00:25:05.880" video="qanda-test" id="subtitle"]]
+[[!template text="""that. So thanks for pointing that out.""" start="00:25:07.480" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 3]: We are trying to cover as much as we can.""" start="00:25:14.620" video="qanda-test" id="subtitle"]]
+[[!template text="""It's almost impossible for org.""" start="00:25:17.520" video="qanda-test" id="subtitle"]]
+[[!template text="""But yeah, we keep adding more tests.""" start="00:25:20.500" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: That's great.""" start="00:25:22.780" video="qanda-test" id="subtitle"]]
+[[!template text="""Someone's typing. I don't know.""" start="00:25:52.720" video="qanda-test" id="subtitle"]]
+[[!template text="""Any more questions? No?""" start="00:25:54.340" video="qanda-test" id="subtitle"]]
+[[!template text="""Okay, then I'll go back and try to document""" start="00:26:01.060" video="qanda-test" id="subtitle"]]
+[[!template text="""this in the etherpad. Thank you everybody for""" start="00:26:05.200" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: Thank you guys. Great work.""" start="00:26:08.860" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 0]: joining. Great. Thank you.""" start="00:26:09.400" video="qanda-test" id="subtitle"]]
+[[!template text="""Take care. Bye-bye.""" start="00:26:11.100" video="qanda-test" id="subtitle"]]
+[[!template text="""[Speaker 1]: Take care. Bye. Silence.""" start="00:26:15.060" video="qanda-test" id="subtitle"]]
+
+Questions or comments? Please e-mail [matsl@gnu.org](mailto:matsl@gnu.org?subject=Comment%20for%20EmacsConf%202023%20test%3A%20What%20I%20learned%20by%20writing%20test%20cases%20for%20GNU%20Hyperbole)
+
+
+<!-- End of emacsconf-publish-after-page -->