Wednesday, 19 August 2020

Android Test cases can only be debugged in debug mode after 10 minutes of waiting

It was working before. But now it doesn't anymore. The IDE just shows "Instantiating tests...". But when I wait for 10 minutes, then all of a sudden it does work? The machine is a Macbook Pro, Mid 2015. The problem only occurs on androidTest, the test directory works fine.

@LargeTest
@RunWith(AndroidJUnit4::class)
class SomeTestClass {

    @get:Rule
    var activityTestRule = ActivityTestRule(
            NavigationActivity::class.java, false, false)

    @Before
    fun before() {
        Timber.d("When debugging, this triggers only after about 10 minutes.")
    }

    @Test
    fun testContents() {
        Assert.assertEquals(0, 0)
    }    
}

The log keeps outputting this:

D/EZIO_NLOG: watchdog_routine executed!
D/EZIO_NLOG: check1 
    check1 
    check2 
    check2 

Tried the following things:

  1. File, Invalidate Cache / Restart
  2. Tried this answer. But it seems to be outdated.
  3. Edit Configurations..., Selected "All in Package", "Class" and "Method". None of them work.
  4. When I wait really long, like 10 minutes, then all of a sudden it triggers and works.

enter image description here enter image description here



from Android Test cases can only be debugged in debug mode after 10 minutes of waiting

Multiple animations in python with matplotlib

I would like to use matplotlib's animation capabilities to display and save multiple animations. Previously, I was just using pyplot with a short pause at each step to fake the animation, but I did not find a way to save these "animations" as videos, so I'm switching to using the real animations. Here is a dummy version of my code (which will run) when I started:

from matplotlib import pyplot as plt
import numpy as np

class Hallway:
    def __init__(self):
        self.end_pos = 5
        self.cur_pos = 0

    def setup(self):
        self.cur_pos = 0

    def go(self, decision):
        if decision == 0 and self.cur_pos > 0:
            self.cur_pos -= 1
        elif decision == 1:
            self.cur_pos += 1
        done = self.cur_pos >= self.end_pos
        return done
    
    def draw(self, fig):
        fig.clear()
        ax = fig.gca()
        ax.set(xlim=(-0.5, 5.5), ylim=(-0.5, 0.5))
        ax.scatter(self.cur_pos, 0., s=350)
        plt.draw()
        plt.pause(0.01)

sim = Hallway()
for num_sim in range(5):
    print("running simulation {}".format(num_sim))
    sim.setup()
    sim.draw(plt.gcf())
    while True:
        done = sim.go(np.random.randint(0,2))
        sim.draw(plt.gcf())
        if done:
            break
    # Save animation here

Key things to note in here:

  1. The next state of the Hallway generated with go
  2. The frames are generated with draw
  3. The done condition indicates when the simulation should end
  4. Once an animation ends, I want to save it, but we're not done! After saving the animation, I want to launch a new one. This will happen 5 times with the outer loop.

So I changed my code around so that I could use an animation object, and this is what it is now:

from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

class Hallway:
    def __init__(self):
        self.end_pos = 5
        self.cur_pos = 0

    def setup(self):
        self.cur_pos = 0

    def go(self, decision):
        if decision == 0 and self.cur_pos > 0:
            self.cur_pos -= 1
        elif decision == 1:
            self.cur_pos += 1
        done = self.cur_pos >= self.end_pos
        return done
    
    def draw(self, fig):
        fig.clear()
        ax = fig.gca()
        ax.set(xlim=(-0.5, 5.5), ylim=(-0.5, 0.5))
        ax.scatter(self.cur_pos, 0., s=350)
        plt.draw()
        plt.pause(0.01)

sim = Hallway()
for num_sim in range(5):
    print("running simulation {}".format(num_sim))
    sim.setup()
    all_done = False
    fig = plt.figure()

    def gen_frame_until_done(): # Using a generator to give me frames as long as not all_done
        global all_done
        i = 0
        while not all_done:
            i += 1
            yield i
    
    def animate(i): # Animate function takes the place of the while loop
        sim.draw(fig)
        done = sim.go(np.random.randint(0,2))
        if done:
            global all_done
            all_done = True
            sim.draw(fig)
    
    anim = FuncAnimation(fig, animate, frames=gen_frame_until_done, repeat=False)
    plt.show()
    # anim.save(...)

This will run, but it won't quite give me what I want. It will show only one animation and the terminal will show running simulation 0. When all_done is triggered and the simulation is over, the program will wait for me to exit the plot window. Once I exit, the program will continue to the next simulation and repeat.

I don't like that I have to manually exit the window. I got a little hack semi-working by replacing the blocking plt.show() with

plt.show(block=False)
plt.pause(3)
plt.close()

This will allow the program to continue without having to manually exit the window. However, it will only allow 3 seconds of the animation to display before going on to the next one.

What I want:

  • I want to be able to display the simulation until it is over. When it is over, I want the window to automatically close.
  • I want the next simulation to run with a new animation window right after the previous one.

Again, I'm using the animation objects because I need to be able to save the animations as videos. But if there's another way to do this, I'm definitely open to it.



from Multiple animations in python with matplotlib

Combining Python trace information and logging

I'm trying to write a highly modular Python logging system (using the logging module) and include information from the trace module in the log message.

For example, I want to be able to write a line of code like:

my_logger.log_message(MyLogFilter, "this is a message")

and have it include the trace of where the "log_message" call was made, instead of the actual logger call itself.

I almost have the following code working except for the fact that the trace information is from the logging.debug() call rather than the my_logger.log_message() one.

class MyLogFilter(logging.Filter):

    def __init__(self):
        self.extra = {"error_code": 999}
        self.level = "debug"

    def filter(self, record):
        for key in self.extra.keys():
           setattr(record, key, self.extra[key])

class myLogger(object):

    def __init__(self):
        fid = logging.FileHandler("test.log")
        formatter = logging.Formatter('%(pathname)s:%(lineno)i, %(error_code)%I, %(message)s' 
        fid.setFormatter(formatter)

        self.my_logger = logging.getLogger(name="test")
        self.my_logger.setLevel(logging.DEBUG)
        self.my_logger.addHandler(fid)

    def log_message(self, lfilter, message):
        xfilter = lfilter()
        self.my_logger.addFilter(xfilter)
        log_funct = getattr(self.logger, xfilter.level)
        log_funct(message)

if __name__ == "__main__":

    logger = myLogger()
    logger.log_message(MyLogFilter, "debugging")

This is a lot of trouble to go through in order to make a simple logging.debug call but in reality, I will have a list of many different versions of MyLogFilter at different logging levels that contain different values of the "error_code" attribute and I'm trying to make the log_message() call as short and sweet as possible because it will be repeated numerous times.

I would appreciate any information about how to do what I want to, or if I'm completely off on the wrong track and if that's the case, what I should be doing instead.

I would like to stick to the internal python modules of "logging" and "trace" if that's possible instead of using any external solutions.



from Combining Python trace information and logging