diff mbox series

[v5,02/10] testing/infra: split runtime test from BRTest

Message ID 20180512025833.22998-3-ricardo.martincoski@gmail.com
State Superseded
Headers show
Series tests for git download infra v5 | expand

Commit Message

Ricardo Martincoski May 12, 2018, 2:58 a.m. UTC
From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>

Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
exactly like BRTest currently does.
It will avoid duplicating code when adding a common class to test the
git download infra.

Change all current test cases to use the new class.
Do this by first using automatic replace:
$ find support/testing/ -name '*.py' | \
  xargs grep -l BRTest | \
  xargs sed -i \
    -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
    -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
and then manually add code to import runtimetest in test_external.py to
avoid this error:
 AttributeError: 'module' object has no attribute 'LoadTestsFailure'
This explicit import was not need before because run-tests imports
BRTest and this is the only test file that do not use the defconfig
fragments from basetest.py in its code.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
Cc: Arnout Vandecappelle <arnout@mind.be>
---
WARNING: this patch changes all current test cases, so if a new test case was
applied after this patch was sent, 'git am' will apply this patch cleanly, yet
any testcase created in the meantime will be broken.
But I can refresh it if need. It will probably only need the automatic replace
from the commit log to be re-run.

Changes v4 -> v5:
  - no changes

Changes v3 -> v4:
  - re-run the automatic replace command

Changes v2 -> v3:
  - new patch
  - search for "RuntimeTestBase" in
    http://patchwork.ozlabs.org/patch/806161/
---
 support/testing/infra/basetest.py             | 10 --------
 support/testing/infra/runtimetest.py          | 23 +++++++++++++++++++
 support/testing/tests/boot/test_atf.py        |  7 +++---
 .../testing/tests/core/test_post_scripts.py   |  3 ++-
 .../testing/tests/core/test_rootfs_overlay.py |  3 ++-
 support/testing/tests/core/test_timezone.py   |  7 +++---
 support/testing/tests/fs/test_ext.py          |  9 ++++----
 support/testing/tests/fs/test_iso9660.py      | 13 ++++++-----
 support/testing/tests/fs/test_jffs2.py        |  3 ++-
 support/testing/tests/fs/test_squashfs.py     |  3 ++-
 support/testing/tests/fs/test_ubi.py          |  3 ++-
 support/testing/tests/fs/test_yaffs2.py       |  3 ++-
 support/testing/tests/init/base.py            |  3 ++-
 .../testing/tests/package/test_dropbear.py    |  3 ++-
 support/testing/tests/package/test_python.py  |  3 ++-
 support/testing/tests/package/test_rust.py    |  3 ++-
 .../testing/tests/package/test_syslog_ng.py   |  3 ++-
 .../testing/tests/toolchain/test_external.py  |  3 ++-
 18 files changed, 67 insertions(+), 38 deletions(-)
 create mode 100644 support/testing/infra/runtimetest.py

Comments

Arnout Vandecappelle Feb. 4, 2019, 3:55 p.m. UTC | #1
On 12/05/2018 04:58, Ricardo Martincoski wrote:
> From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> 
> Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
> exactly like BRTest currently does.
> It will avoid duplicating code when adding a common class to test the
> git download infra.
> 
> Change all current test cases to use the new class.
> Do this by first using automatic replace:
> $ find support/testing/ -name '*.py' | \
>   xargs grep -l BRTest | \
>   xargs sed -i \
>     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
>     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
> and then manually add code to import runtimetest in test_external.py to
> avoid this error:
>  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
> This explicit import was not need before because run-tests imports
> BRTest and this is the only test file that do not use the defconfig
> fragments from basetest.py in its code.
> 
> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> Cc: Arnout Vandecappelle <arnout@mind.be>
> ---
> WARNING: this patch changes all current test cases, so if a new test case was
> applied after this patch was sent, 'git am' will apply this patch cleanly, yet
> any testcase created in the meantime will be broken.
> But I can refresh it if need. It will probably only need the automatic replace
> from the commit log to be re-run.

 This seems to be an optimisation rather than a requirement for the other
patches, so I haven't applied this - it needs to be refreshed first.

 If you do so before Wednesday, we might still apply it.

 Regards,
 Arnout
Matt Weber Feb. 4, 2019, 6:19 p.m. UTC | #2
Ricardo,

On Mon, Feb 4, 2019 at 9:55 AM Arnout Vandecappelle <arnout@mind.be> wrote:
>
>
>
> On 12/05/2018 04:58, Ricardo Martincoski wrote:
> > From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> >
> > Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
> > exactly like BRTest currently does.
> > It will avoid duplicating code when adding a common class to test the
> > git download infra.
> >
> > Change all current test cases to use the new class.
> > Do this by first using automatic replace:
> > $ find support/testing/ -name '*.py' | \
> >   xargs grep -l BRTest | \
> >   xargs sed -i \
> >     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
> >     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
> > and then manually add code to import runtimetest in test_external.py to
> > avoid this error:
> >  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
> > This explicit import was not need before because run-tests imports
> > BRTest and this is the only test file that do not use the defconfig
> > fragments from basetest.py in its code.
> >
> > Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> > Cc: Arnout Vandecappelle <arnout@mind.be>
> > ---
> > WARNING: this patch changes all current test cases, so if a new test case was
> > applied after this patch was sent, 'git am' will apply this patch cleanly, yet
> > any testcase created in the meantime will be broken.
> > But I can refresh it if need. It will probably only need the automatic replace
> > from the commit log to be re-run.
>
>  This seems to be an optimisation rather than a requirement for the other
> patches, so I haven't applied this - it needs to be refreshed first.
>
>  If you do so before Wednesday, we might still apply it.
>

Let me know if you won't have a chance and I'll get it updated for tomorrow.

Matt
Matt Weber Feb. 4, 2019, 7:42 p.m. UTC | #3
Ricardo,

On Mon, Feb 4, 2019 at 12:19 PM Matthew Weber
<matthew.weber@rockwellcollins.com> wrote:
>
> Ricardo,
>
> On Mon, Feb 4, 2019 at 9:55 AM Arnout Vandecappelle <arnout@mind.be> wrote:
> >
> >
> >
> > On 12/05/2018 04:58, Ricardo Martincoski wrote:
> > > From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> > >
> > > Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
> > > exactly like BRTest currently does.
> > > It will avoid duplicating code when adding a common class to test the
> > > git download infra.
> > >
> > > Change all current test cases to use the new class.
> > > Do this by first using automatic replace:
> > > $ find support/testing/ -name '*.py' | \
> > >   xargs grep -l BRTest | \
> > >   xargs sed -i \
> > >     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
> > >     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
> > > and then manually add code to import runtimetest in test_external.py to
> > > avoid this error:
> > >  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
> > > This explicit import was not need before because run-tests imports
> > > BRTest and this is the only test file that do not use the defconfig
> > > fragments from basetest.py in its code.
> > >
> > > Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> > > Cc: Arnout Vandecappelle <arnout@mind.be>
> > > ---
> > > WARNING: this patch changes all current test cases, so if a new test case was
> > > applied after this patch was sent, 'git am' will apply this patch cleanly, yet
> > > any testcase created in the meantime will be broken.
> > > But I can refresh it if need. It will probably only need the automatic replace
> > > from the commit log to be re-run.
> >
> >  This seems to be an optimisation rather than a requirement for the other
> > patches, so I haven't applied this - it needs to be refreshed first.
> >
> >  If you do so before Wednesday, we might still apply it.
> >
>
> Let me know if you won't have a chance and I'll get it updated for tomorrow.
>

Ricardo, I just realized the scope of retesting this.  I went ahead
and fixed up the patch for v6 (this included rebase changes for
br2-external and new test cases needing the new class).  I also kicked
off a test run to check it out and I'll send the patch later if things
pass.

Matt
Ricardo Martincoski Feb. 5, 2019, 1 a.m. UTC | #4
Hello,

+ Matt

On Mon, Feb 04, 2019 at 01:55 PM, Arnout Vandecappelle wrote:

> On 12/05/2018 04:58, Ricardo Martincoski wrote:
>> From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
>> 
>> Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
>> exactly like BRTest currently does.
>> It will avoid duplicating code when adding a common class to test the
>> git download infra.
>> 
>> Change all current test cases to use the new class.
>> Do this by first using automatic replace:
>> $ find support/testing/ -name '*.py' | \
>>   xargs grep -l BRTest | \
>>   xargs sed -i \
>>     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
>>     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
>> and then manually add code to import runtimetest in test_external.py to
>> avoid this error:
>>  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
>> This explicit import was not need before because run-tests imports
>> BRTest and this is the only test file that do not use the defconfig
>> fragments from basetest.py in its code.
>> 
>> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
>> Cc: Arnout Vandecappelle <arnout@mind.be>
>> ---
>> WARNING: this patch changes all current test cases, so if a new test case was
>> applied after this patch was sent, 'git am' will apply this patch cleanly, yet
>> any testcase created in the meantime will be broken.
>> But I can refresh it if need. It will probably only need the automatic replace
>> from the commit log to be re-run.
> 
>  This seems to be an optimisation rather than a requirement for the other
> patches, so I haven't applied this - it needs to be refreshed first.

It's an optimisation, but I failed to describe why it should be done first...

The download test cases do not need to build anything before they run, so by
splitting the two classes and making test_git to inherit from the new BRTest
instead of RuntimeTestBase makes the download test cases to run really fast.
The two test cases already on master, after applying and refreshing this patch,
run in 35 seconds total in my machine.
Less than 2 minutes each in the Gitlab CI auto-scale runners:
https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194310
https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194313
Unfortunately there is still some problem in my WIP refresh of the patch, so I
can't send it now.

> 
>  If you do so before Wednesday, we might still apply it.

Unfortunately it's unlikely I can do in time.


Regards,
Ricardo
Matt Weber Feb. 5, 2019, 1:12 a.m. UTC | #5
Ricardo,
On Mon, Feb 4, 2019 at 7:00 PM Ricardo Martincoski
<ricardo.martincoski@gmail.com> wrote:
>
> Hello,
>
> + Matt
>
> On Mon, Feb 04, 2019 at 01:55 PM, Arnout Vandecappelle wrote:
>
> > On 12/05/2018 04:58, Ricardo Martincoski wrote:
> >> From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> >>
> >> Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
> >> exactly like BRTest currently does.
> >> It will avoid duplicating code when adding a common class to test the
> >> git download infra.
> >>
> >> Change all current test cases to use the new class.
> >> Do this by first using automatic replace:
> >> $ find support/testing/ -name '*.py' | \
> >>   xargs grep -l BRTest | \
> >>   xargs sed -i \
> >>     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
> >>     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
> >> and then manually add code to import runtimetest in test_external.py to
> >> avoid this error:
> >>  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
> >> This explicit import was not need before because run-tests imports
> >> BRTest and this is the only test file that do not use the defconfig
> >> fragments from basetest.py in its code.
> >>
> >> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> >> Cc: Arnout Vandecappelle <arnout@mind.be>
> >> ---
> >> WARNING: this patch changes all current test cases, so if a new test case was
> >> applied after this patch was sent, 'git am' will apply this patch cleanly, yet
> >> any testcase created in the meantime will be broken.
> >> But I can refresh it if need. It will probably only need the automatic replace
> >> from the commit log to be re-run.
> >
> >  This seems to be an optimisation rather than a requirement for the other
> > patches, so I haven't applied this - it needs to be refreshed first.
>
> It's an optimisation, but I failed to describe why it should be done first...
>
> The download test cases do not need to build anything before they run, so by
> splitting the two classes and making test_git to inherit from the new BRTest
> instead of RuntimeTestBase makes the download test cases to run really fast.
> The two test cases already on master, after applying and refreshing this patch,
> run in 35 seconds total in my machine.
> Less than 2 minutes each in the Gitlab CI auto-scale runners:
> https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194310
> https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194313

If I understand correctly those are the only two at this point that
should use the BRTest class instead of the RuntimeTestBase, right?

> Unfortunately there is still some problem in my WIP refresh of the patch, so I
> can't send it now.
>
> >
> >  If you do so before Wednesday, we might still apply it.
>
> Unfortunately it's unlikely I can do in time.
>

I might be in the same situation after looking at the build failures.
I'll spend a bit more on it tonight but there are a lot of tests to
either spot check or run all.  I'm not sure yet if it is my build
machine's OS and python version or qemu at this point.

Matt
Ricardo Martincoski Feb. 5, 2019, 1:19 a.m. UTC | #6
Hello,

On Mon, Feb 04, 2019 at 05:42 PM, Matthew Weber wrote:

> On Mon, Feb 4, 2019 at 12:19 PM Matthew Weber wrote:
>>
>> On Mon, Feb 4, 2019 at 9:55 AM Arnout Vandecappelle <arnout@mind.be> wrote:
[snip]
>> >  This seems to be an optimisation rather than a requirement for the other
>> > patches, so I haven't applied this - it needs to be refreshed first.
>> >
>> >  If you do so before Wednesday, we might still apply it.
>> >
>>
>> Let me know if you won't have a chance and I'll get it updated for tomorrow.
>>
> 
> Ricardo, I just realized the scope of retesting this.  I went ahead
> and fixed up the patch for v6 (this included rebase changes for
> br2-external and new test cases needing the new class).  I also kicked
> off a test run to check it out and I'll send the patch later if things
> pass.

If you find the time, please do.
It's unlikely I have enough time before Wednesday.

I started to refresh the patch, but there are some test cases failing, I don't
know why. Probably I made some mistake.
https://gitlab.com/RicardoMartincoski/buildroot/pipelines/46127542

I did not checked if any of these test cases already fail without this patch.
I just kicked off a test run for this:
https://gitlab.com/RicardoMartincoski/buildroot/pipelines/46142012


Regards,
Ricardo
Ricardo Martincoski Feb. 5, 2019, 1:47 a.m. UTC | #7
Hello,

On Mon, Feb 04, 2019 at 11:12 PM, Matthew Weber wrote:

> On Mon, Feb 4, 2019 at 7:00 PM Ricardo Martincoski wrote:
[snip]
>> The download test cases do not need to build anything before they run, so by
>> splitting the two classes and making test_git to inherit from the new BRTest
>> instead of RuntimeTestBase makes the download test cases to run really fast.
>> The two test cases already on master, after applying and refreshing this patch,
>> run in 35 seconds total in my machine.
>> Less than 2 minutes each in the Gitlab CI auto-scale runners:
>> https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194310
>> https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194313
> 
> If I understand correctly those are the only two at this point that
> should use the BRTest class instead of the RuntimeTestBase, right?

Right.

> 
>> Unfortunately there is still some problem in my WIP refresh of the patch, so I
>> can't send it now.
>>
>> >
>> >  If you do so before Wednesday, we might still apply it.
>>
>> Unfortunately it's unlikely I can do in time.
>>
> 
> I might be in the same situation after looking at the build failures.

No problem. We can do it later. Thank you for looking into this.

> I'll spend a bit more on it tonight but there are a lot of tests to
> either spot check or run all.  I'm not sure yet if it is my build
> machine's OS and python version or qemu at this point.

I found myself in this situation a few times in the past :-)
You can also download the docker image and run the test cases inside it.


Regards,
Ricardo
Arnout Vandecappelle Feb. 5, 2019, 8:29 a.m. UTC | #8
On 05/02/2019 02:19, Ricardo Martincoski wrote:
> Hello,
> 
> On Mon, Feb 04, 2019 at 05:42 PM, Matthew Weber wrote:
> 
>> On Mon, Feb 4, 2019 at 12:19 PM Matthew Weber wrote:
>>>
>>> On Mon, Feb 4, 2019 at 9:55 AM Arnout Vandecappelle <arnout@mind.be> wrote:
> [snip]
>>>>  This seems to be an optimisation rather than a requirement for the other
>>>> patches, so I haven't applied this - it needs to be refreshed first.
>>>>
>>>>  If you do so before Wednesday, we might still apply it.
>>>>
>>>
>>> Let me know if you won't have a chance and I'll get it updated for tomorrow.
>>>
>>
>> Ricardo, I just realized the scope of retesting this.  I went ahead
>> and fixed up the patch for v6 (this included rebase changes for
>> br2-external and new test cases needing the new class).  I also kicked
>> off a test run to check it out and I'll send the patch later if things
>> pass.
> 
> If you find the time, please do.
> It's unlikely I have enough time before Wednesday.
> 
> I started to refresh the patch, but there are some test cases failing, I don't
> know why. Probably I made some mistake.
> https://gitlab.com/RicardoMartincoski/buildroot/pipelines/46127542

 I think these failures are already happening in master:
https://gitlab.com/buildroot.org/buildroot/pipelines/45710311

 Someone really should look at the CI results :-)

 Regards,
 Arnout

> 
> I did not checked if any of these test cases already fail without this patch.
> I just kicked off a test run for this:
> https://gitlab.com/RicardoMartincoski/buildroot/pipelines/46142012
> 
> 
> Regards,
> Ricardo
>
Matt Weber Feb. 5, 2019, 9:28 a.m. UTC | #9
Ricardo / Arnout,

On Mon, Feb 4, 2019 at 7:12 PM Matthew Weber
<matthew.weber@rockwellcollins.com> wrote:
>
> Ricardo,
> On Mon, Feb 4, 2019 at 7:00 PM Ricardo Martincoski
> <ricardo.martincoski@gmail.com> wrote:
> >
> > Hello,
> >
> > + Matt
> >
> > On Mon, Feb 04, 2019 at 01:55 PM, Arnout Vandecappelle wrote:
> >
> > > On 12/05/2018 04:58, Ricardo Martincoski wrote:
> > >> From: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> > >>
> > >> Move the setup of emulator to a new class, RuntimeTestBase, that bahaves
> > >> exactly like BRTest currently does.
> > >> It will avoid duplicating code when adding a common class to test the
> > >> git download infra.
> > >>
> > >> Change all current test cases to use the new class.
> > >> Do this by first using automatic replace:
> > >> $ find support/testing/ -name '*.py' | \
> > >>   xargs grep -l BRTest | \
> > >>   xargs sed -i \
> > >>     -e 's,import infra.basetest,\0\nimport infra.runtimetest,g' \
> > >>     -e 's,infra.basetest.BRTest,infra.runtimetest.RuntimeTestBase,g'
> > >> and then manually add code to import runtimetest in test_external.py to
> > >> avoid this error:
> > >>  AttributeError: 'module' object has no attribute 'LoadTestsFailure'
> > >> This explicit import was not need before because run-tests imports
> > >> BRTest and this is the only test file that do not use the defconfig
> > >> fragments from basetest.py in its code.
> > >>
> > >> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br>
> > >> Cc: Arnout Vandecappelle <arnout@mind.be>
> > >> ---
> > >> WARNING: this patch changes all current test cases, so if a new test case was
> > >> applied after this patch was sent, 'git am' will apply this patch cleanly, yet
> > >> any testcase created in the meantime will be broken.
> > >> But I can refresh it if need. It will probably only need the automatic replace
> > >> from the commit log to be re-run.
> > >
> > >  This seems to be an optimisation rather than a requirement for the other
> > > patches, so I haven't applied this - it needs to be refreshed first.
> >
> > It's an optimisation, but I failed to describe why it should be done first...
> >
> > The download test cases do not need to build anything before they run, so by
> > splitting the two classes and making test_git to inherit from the new BRTest
> > instead of RuntimeTestBase makes the download test cases to run really fast.
> > The two test cases already on master, after applying and refreshing this patch,
> > run in 35 seconds total in my machine.
> > Less than 2 minutes each in the Gitlab CI auto-scale runners:
> > https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194310
> > https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/156194313
>
> If I understand correctly those are the only two at this point that
> should use the BRTest class instead of the RuntimeTestBase, right?
>
> > Unfortunately there is still some problem in my WIP refresh of the patch, so I
> > can't send it now.
> >
> > >
> > >  If you do so before Wednesday, we might still apply it.
> >
> > Unfortunately it's unlikely I can do in time.
> >
>
> I might be in the same situation after looking at the build failures.
> I'll spend a bit more on it tonight but there are a lot of tests to
> either spot check or run all.  I'm not sure yet if it is my build
> machine's OS and python version or qemu at this point.
>

Here's the v6 and I'll start looking through the differences in the CI
reports (looked similar enough I figured I'd get the patch out first).
http://patchwork.ozlabs.org/patch/1036559/
diff mbox series

Patch

diff --git a/support/testing/infra/basetest.py b/support/testing/infra/basetest.py
index f3f13ad97f..4773312585 100644
--- a/support/testing/infra/basetest.py
+++ b/support/testing/infra/basetest.py
@@ -3,7 +3,6 @@  import os
 import datetime
 
 from infra.builder import Builder
-from infra.emulator import Emulator
 
 BASIC_TOOLCHAIN_CONFIG = \
     """
@@ -41,7 +40,6 @@  class BRTest(unittest.TestCase):
         super(BRTest, self).__init__(names)
         self.testname = self.__class__.__name__
         self.builddir = self.outputdir and os.path.join(self.outputdir, self.testname)
-        self.emulator = None
         self.config += '\nBR2_DL_DIR="{}"\n'.format(self.downloaddir)
         self.config += "\nBR2_JLEVEL={}\n".format(self.jlevel)
 
@@ -57,17 +55,9 @@  class BRTest(unittest.TestCase):
             self.b.delete()
 
         if not self.b.is_finished():
-            self.show_msg("Building")
             self.b.configure()
-            self.b.build()
-            self.show_msg("Building done")
-
-        self.emulator = Emulator(self.builddir, self.downloaddir,
-                                 self.logtofile, self.timeout_multiplier)
 
     def tearDown(self):
         self.show_msg("Cleaning up")
-        if self.emulator:
-            self.emulator.stop()
         if self.b and not self.keepbuilds:
             self.b.delete()
diff --git a/support/testing/infra/runtimetest.py b/support/testing/infra/runtimetest.py
new file mode 100644
index 0000000000..68bb03d091
--- /dev/null
+++ b/support/testing/infra/runtimetest.py
@@ -0,0 +1,23 @@ 
+from infra.basetest import BRTest
+from infra.emulator import Emulator
+
+
+class RuntimeTestBase(BRTest):
+    def __init__(self, names):
+        super(RuntimeTestBase, self).__init__(names)
+        self.emulator = None
+
+    def setUp(self):
+        super(RuntimeTestBase, self).setUp()
+        if not self.b.is_finished():
+            self.show_msg("Building")
+            self.b.build()
+            self.show_msg("Building done")
+
+        self.emulator = Emulator(self.builddir, self.downloaddir,
+                                 self.logtofile, self.timeout_multiplier)
+
+    def tearDown(self):
+        if self.emulator:
+            self.emulator.stop()
+        super(RuntimeTestBase, self).tearDown()
diff --git a/support/testing/tests/boot/test_atf.py b/support/testing/tests/boot/test_atf.py
index 75cea01fc8..0ea486fb5b 100644
--- a/support/testing/tests/boot/test_atf.py
+++ b/support/testing/tests/boot/test_atf.py
@@ -1,7 +1,8 @@ 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestATFVexpress(infra.basetest.BRTest):
+class TestATFVexpress(infra.runtimetest.RuntimeTestBase):
     config = \
         """
         BR2_aarch64=y
@@ -25,7 +26,7 @@  class TestATFVexpress(infra.basetest.BRTest):
         pass
 
 
-class TestATFAllwinner(infra.basetest.BRTest):
+class TestATFAllwinner(infra.runtimetest.RuntimeTestBase):
     config = \
         """
         BR2_aarch64=y
@@ -54,7 +55,7 @@  class TestATFAllwinner(infra.basetest.BRTest):
         pass
 
 
-class TestATFMarvell(infra.basetest.BRTest):
+class TestATFMarvell(infra.runtimetest.RuntimeTestBase):
     config = \
         """
         BR2_aarch64=y
diff --git a/support/testing/tests/core/test_post_scripts.py b/support/testing/tests/core/test_post_scripts.py
index a0e5b6b454..c4dfb91550 100644
--- a/support/testing/tests/core/test_post_scripts.py
+++ b/support/testing/tests/core/test_post_scripts.py
@@ -2,9 +2,10 @@  import os
 import csv
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestPostScripts(infra.basetest.BRTest):
+class TestPostScripts(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_INIT_NONE=y
diff --git a/support/testing/tests/core/test_rootfs_overlay.py b/support/testing/tests/core/test_rootfs_overlay.py
index fedd40d8ac..66b5531221 100644
--- a/support/testing/tests/core/test_rootfs_overlay.py
+++ b/support/testing/tests/core/test_rootfs_overlay.py
@@ -2,13 +2,14 @@  import os
 import subprocess
 
 import infra.basetest
+import infra.runtimetest
 
 
 def compare_file(file1, file2):
     return subprocess.call(["cmp", file1, file2])
 
 
-class TestRootfsOverlay(infra.basetest.BRTest):
+class TestRootfsOverlay(infra.runtimetest.RuntimeTestBase):
 
     rootfs_overlay_path = infra.filepath("tests/core/rootfs-overlay")
 
diff --git a/support/testing/tests/core/test_timezone.py b/support/testing/tests/core/test_timezone.py
index 050624e0aa..dca38bebe8 100644
--- a/support/testing/tests/core/test_timezone.py
+++ b/support/testing/tests/core/test_timezone.py
@@ -1,6 +1,7 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
 def boot_armv5_cpio(emulator, builddir):
@@ -10,7 +11,7 @@  def boot_armv5_cpio(emulator, builddir):
         emulator.login()
 
 
-class TestNoTimezone(infra.basetest.BRTest):
+class TestNoTimezone(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         # BR2_TARGET_TZ_INFO is not set
@@ -26,7 +27,7 @@  class TestNoTimezone(infra.basetest.BRTest):
         self.assertEqual(tz[0].strip(), "UTC")
 
 
-class TestGlibcAllTimezone(infra.basetest.BRTest):
+class TestGlibcAllTimezone(infra.runtimetest.RuntimeTestBase):
     config = \
         """
         BR2_arm=y
@@ -48,7 +49,7 @@  class TestGlibcAllTimezone(infra.basetest.BRTest):
         self.assertEqual(tz[0].strip(), "CET")
 
 
-class TestGlibcNonDefaultLimitedTimezone(infra.basetest.BRTest):
+class TestGlibcNonDefaultLimitedTimezone(infra.runtimetest.RuntimeTestBase):
     config = \
         """
         BR2_arm=y
diff --git a/support/testing/tests/fs/test_ext.py b/support/testing/tests/fs/test_ext.py
index f5f9e9fdf1..a8f68bc54c 100644
--- a/support/testing/tests/fs/test_ext.py
+++ b/support/testing/tests/fs/test_ext.py
@@ -2,6 +2,7 @@  import os
 import subprocess
 
 import infra.basetest
+import infra.runtimetest
 
 VOLNAME_PROP = "Filesystem volume name"
 REVISION_PROP = "Filesystem revision #"
@@ -41,7 +42,7 @@  def boot_img_and_check_fs_type(emulator, builddir, fs_type):
     return exit_code
 
 
-class TestExt2(infra.basetest.BRTest):
+class TestExt2(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_EXT2=y
@@ -60,7 +61,7 @@  class TestExt2(infra.basetest.BRTest):
         self.assertEqual(exit_code, 0)
 
 
-class TestExt2r1(infra.basetest.BRTest):
+class TestExt2r1(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_EXT2=y
@@ -80,7 +81,7 @@  class TestExt2r1(infra.basetest.BRTest):
         self.assertEqual(exit_code, 0)
 
 
-class TestExt3(infra.basetest.BRTest):
+class TestExt3(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_EXT2=y
@@ -99,7 +100,7 @@  class TestExt3(infra.basetest.BRTest):
         self.assertEqual(exit_code, 0)
 
 
-class TestExt4(infra.basetest.BRTest):
+class TestExt4(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_EXT2=y
diff --git a/support/testing/tests/fs/test_iso9660.py b/support/testing/tests/fs/test_iso9660.py
index 68f4840852..77255ac93b 100644
--- a/support/testing/tests/fs/test_iso9660.py
+++ b/support/testing/tests/fs/test_iso9660.py
@@ -1,6 +1,7 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 BASIC_CONFIG = \
     """
@@ -47,7 +48,7 @@  def test_touch_file(emulator):
 # Grub 2
 
 
-class TestIso9660Grub2External(infra.basetest.BRTest):
+class TestIso9660Grub2External(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
@@ -67,7 +68,7 @@  class TestIso9660Grub2External(infra.basetest.BRTest):
         self.assertEqual(exit_code, 1)
 
 
-class TestIso9660Grub2ExternalCompress(infra.basetest.BRTest):
+class TestIso9660Grub2ExternalCompress(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
@@ -88,7 +89,7 @@  class TestIso9660Grub2ExternalCompress(infra.basetest.BRTest):
         self.assertEqual(exit_code, 1)
 
 
-class TestIso9660Grub2Internal(infra.basetest.BRTest):
+class TestIso9660Grub2Internal(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
@@ -111,7 +112,7 @@  class TestIso9660Grub2Internal(infra.basetest.BRTest):
 # Syslinux
 
 
-class TestIso9660SyslinuxExternal(infra.basetest.BRTest):
+class TestIso9660SyslinuxExternal(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
@@ -130,7 +131,7 @@  class TestIso9660SyslinuxExternal(infra.basetest.BRTest):
         self.assertEqual(exit_code, 1)
 
 
-class TestIso9660SyslinuxExternalCompress(infra.basetest.BRTest):
+class TestIso9660SyslinuxExternalCompress(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
@@ -150,7 +151,7 @@  class TestIso9660SyslinuxExternalCompress(infra.basetest.BRTest):
         self.assertEqual(exit_code, 1)
 
 
-class TestIso9660SyslinuxInternal(infra.basetest.BRTest):
+class TestIso9660SyslinuxInternal(infra.runtimetest.RuntimeTestBase):
     config = BASIC_CONFIG + \
         """
         BR2_TARGET_ROOTFS_ISO9660=y
diff --git a/support/testing/tests/fs/test_jffs2.py b/support/testing/tests/fs/test_jffs2.py
index 2ff5099180..8f73cf1f06 100644
--- a/support/testing/tests/fs/test_jffs2.py
+++ b/support/testing/tests/fs/test_jffs2.py
@@ -2,6 +2,7 @@  import os
 import subprocess
 
 import infra.basetest
+import infra.runtimetest
 
 
 def jffs2dump_find_file(files_list, fname):
@@ -12,7 +13,7 @@  def jffs2dump_find_file(files_list, fname):
     return False
 
 
-class TestJffs2(infra.basetest.BRTest):
+class TestJffs2(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_JFFS2=y
diff --git a/support/testing/tests/fs/test_squashfs.py b/support/testing/tests/fs/test_squashfs.py
index 066c054342..f80149f9d9 100644
--- a/support/testing/tests/fs/test_squashfs.py
+++ b/support/testing/tests/fs/test_squashfs.py
@@ -2,9 +2,10 @@  import os
 import subprocess
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestSquashfs(infra.basetest.BRTest):
+class TestSquashfs(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_SQUASHFS=y
diff --git a/support/testing/tests/fs/test_ubi.py b/support/testing/tests/fs/test_ubi.py
index 015d82f769..c724f4f740 100644
--- a/support/testing/tests/fs/test_ubi.py
+++ b/support/testing/tests/fs/test_ubi.py
@@ -2,9 +2,10 @@  import subprocess
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestUbi(infra.basetest.BRTest):
+class TestUbi(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_UBIFS=y
diff --git a/support/testing/tests/fs/test_yaffs2.py b/support/testing/tests/fs/test_yaffs2.py
index b60e90e660..c7c8c1f724 100644
--- a/support/testing/tests/fs/test_yaffs2.py
+++ b/support/testing/tests/fs/test_yaffs2.py
@@ -1,9 +1,10 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestYaffs2(infra.basetest.BRTest):
+class TestYaffs2(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         infra.basetest.MINIMAL_CONFIG + \
         """
diff --git a/support/testing/tests/init/base.py b/support/testing/tests/init/base.py
index 75cfbe9c59..1b736af657 100644
--- a/support/testing/tests/init/base.py
+++ b/support/testing/tests/init/base.py
@@ -1,9 +1,10 @@ 
 import os
 import subprocess
 import infra.basetest
+import infra.runtimetest
 
 
-class InitSystemBase(infra.basetest.BRTest):
+class InitSystemBase(infra.runtimetest.RuntimeTestBase):
 
     def start_emulator(self, fs_type, kernel=None, dtb=None, init=None):
         img = os.path.join(self.builddir, "images", "rootfs.{}".format(fs_type))
diff --git a/support/testing/tests/package/test_dropbear.py b/support/testing/tests/package/test_dropbear.py
index 8f7f1fee82..8f7f30e3af 100644
--- a/support/testing/tests/package/test_dropbear.py
+++ b/support/testing/tests/package/test_dropbear.py
@@ -1,9 +1,10 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestDropbear(infra.basetest.BRTest):
+class TestDropbear(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_GENERIC_ROOT_PASSWD="testpwd"
diff --git a/support/testing/tests/package/test_python.py b/support/testing/tests/package/test_python.py
index 26cf49947b..787364c719 100644
--- a/support/testing/tests/package/test_python.py
+++ b/support/testing/tests/package/test_python.py
@@ -1,9 +1,10 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestPythonBase(infra.basetest.BRTest):
+class TestPythonBase(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_TARGET_ROOTFS_CPIO=y
diff --git a/support/testing/tests/package/test_rust.py b/support/testing/tests/package/test_rust.py
index 2dc814f99d..df445f1186 100644
--- a/support/testing/tests/package/test_rust.py
+++ b/support/testing/tests/package/test_rust.py
@@ -4,9 +4,10 @@  import subprocess
 import shutil
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestRustBase(infra.basetest.BRTest):
+class TestRustBase(infra.runtimetest.RuntimeTestBase):
 
     target = 'armv7-unknown-linux-gnueabihf'
     crate = 'hello-world'
diff --git a/support/testing/tests/package/test_syslog_ng.py b/support/testing/tests/package/test_syslog_ng.py
index 0155ef14e4..df6ce8b8d0 100644
--- a/support/testing/tests/package/test_syslog_ng.py
+++ b/support/testing/tests/package/test_syslog_ng.py
@@ -1,9 +1,10 @@ 
 import os
 
 import infra.basetest
+import infra.runtimetest
 
 
-class TestSyslogNg(infra.basetest.BRTest):
+class TestSyslogNg(infra.runtimetest.RuntimeTestBase):
     config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
         """
         BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
diff --git a/support/testing/tests/toolchain/test_external.py b/support/testing/tests/toolchain/test_external.py
index 881d2b00db..b72e19f740 100644
--- a/support/testing/tests/toolchain/test_external.py
+++ b/support/testing/tests/toolchain/test_external.py
@@ -1,5 +1,6 @@ 
 import os
 import infra
+import infra.runtimetest
 
 BASIC_CONFIG = \
     """
@@ -17,7 +18,7 @@  def has_broken_links(path):
     return False
 
 
-class TestExternalToolchain(infra.basetest.BRTest):
+class TestExternalToolchain(infra.runtimetest.RuntimeTestBase):
     def common_check(self):
         # Check for broken symlinks
         for d in ["lib", "usr/lib"]: