Write Fewer Tests in Python

Sqlite has 1000X more code for testing than in actual source code! That’s phenomenal, but it’s common for companies to have 5X-10X more testing code. This seems like an area that programming languages and development tools should tackle. That is, think of ways to reduce the huge amount of extra code written for testing.

As an experiment, I wrote a simple Skiplist in Python 3.5 in a stream-of-consciousness burst of sloppy coding. I used pylint to catch many obvious mistakes. It’s about as good as any decent IDE. After some back and forth I had code that could be loaded into the interpreter.

I next used hypothesis to write tests using the unittest library. This tool is a Python implementation of QuickCheck, a brilliant library for automated property based testing. Consider the following code to test insertion into a skiplist:

def test_insert_integers(self, nums):
    sorted_nums = sorted(nums)
    self.assertEqual(0, len(self.skip))

    for i in nums:

    for i in sorted_nums:
        self.assertIn(i, self.skip)
    for i in self.skip:
        self.assertIn(i, sorted_nums)

    self.assertEqual(len(nums), len(self.skip))

The given decorator tells hypothesis to generate random lists of integers to feed into this function. The function inserts all elements into the skiplist and asserts some properties. hypothesis was able to find lots of interesting bugs in my code by printing a small example that caused the error. Unfortunately, hypothesis doesn’t play well with unittest because this single test method actually runs lots of tests. So it doesn’t run setUp and tearDown correctly. But that’s easy to get around for now.

The next step was to use Python 3.5 type annotations and mypy to do static type checking. You can either write unittests to check all this, or let the tools handle it for you. The type annotations are a bit verbose, and the syntax for adding type declarations for fields is atrocious. Nevertheless, it works really well and caught a few corner cases in untested code. There is a problem, though. I can’t find a way to add constraints on generic types. In my code, I want to say the generic type T must support the __lt__ operator. Right now it seems to work somehow.

Finally, I used PyContracts to write design-by-contract style code. It allows one to write additional constraints on your code. For example, in choosing how many levels a skiplist has, I added a constraint to the constructor @contract(max_level='>0') which verifies the input. I didn’t see many opportunities to add contracts to my code because it’s supposed to allow nearly anything, like a list. While contracts in .NET are fantastic, PyContracts are good enough. Though it needs to play better with 3.5’s typing syntax.

Despite all this I found a bug that could only be discovered by a code review. Searching through a skiplist is supposed to be O(lg n). However, I had failed to begin each level’s search where the previous level left off. So my search was correct, but O(n). How could a test discover bugs that give correct results? It’s really a performance issue that would only be revealed for large N.

Overall using types, contracts and hypothesis seems to catch quite a few errors. The only minor issue is it would be nice if all these things cooperated better. For example, if I state the type of a function parameter then both the contracts and hypothesis should use this information. if I add a contract, then hypothesis should use that to craft random input more efficiently. What techniques could I add next to better test my code?

I Lost My Wallet in El Segundo

Actually I lost my wallet in Venice, CA, but no one wrote a song about that. So what do you do if you lose your wallet while traveling? I had no government ID, no credit/debit cards and no cash. Nothing. Luckily I was traveling with a friend, but if I were alone I’d be screwed. Credit cards were sent to me in 2 days. They would not send debit cards to me, only to my home address.

To get through the TSA without ID it helps to have anything that confirms your identity. I had my new credit cards. FYI: I had a copy of my passport, but they didn’t want copies of anything. Tell the TSA agent you have no ID. They will call a supervisor over. It took a while for the guy to show up, so go to the airport early. You put your name/address on a document. Then they call some other office, give them your info and they ask some questions. I was asked for the last 4-digits of my home phone. Then my previous address (I didn’t remember the zip code). They asked for the name of a close relative. I offered my dad’s name. Then they asked for his birthday. I don’t remember anyone’s birthday; however, it happened to be my dad’s birthday and my phone alert had gone off that morning. I only remember his age because he hit a milestone the previous year. So some quick math and I had his birthdate right. I went through security and then had more checking. They did a quick pat down, the bomb residue test on me and my luggage. They didn’t search anything. Although I look like a terrorist, the whole thing was fine.

In the future, I need to pack some backup. I should leave a debit card in my luggage so I can get cash and buy things. For some reason the TSA guy asked for that, so it might be a more legit form of identity. If you look at the list of valid ID, I only have a passport but I don’t carry it for domestic travel. It might be worth getting a Global Entry card as a backup ID. Alternatively, maybe the state will give me another non-driving ID even if I already have a driver’s license. I can just leave that in my luggage.

One-Way Sync on Windows

I have pictures scattered and duplicated across multiple Windows machines. I want them all on one machine. So if picture [A,B,C] is on machine 1 and [B,C,D] is on the central server, I only want to copy A over. Pretty simple.

I tried to use unison, a fancy synchronization tool that sort of runs on multiple platforms. But I could not figure out how to get it to do this. I tried using “-force”, but it kept synching in both directions. Finally I switched to Windows’ robocopy. The command line is “robocopy /s /xc /xn /xo source-path destination-path”. The first option “/s” says to go down all directories. The other options say don’t copy the file over if the file changed or is older/newer. It’s not a clean way to do it, but it seems to work.

Why I still won’t use Windows

TL;DR: It’s the service and hardware vendors that suck, not the OS.

I upgraded a family member’s computer to Windows 10. It went smoothly and the new OS UI seems fine. The laptop is a Dell XPS 12 (2013). Overall it’s an OK computer if touch is your thing. In doing this I discovered a lot of strange behavior in the hardware/OS interaction that was there before Win10. Things like (1) the computer suddenly wakes from sleep and drains the battery. (2) The USB port that does NOT support Powershare still provides power when the computer is asleep. (3) All the Power Plans have disappeared. And so on…

I expect problems with computers. The issue is it is damn near impossible for a novice to find a solution. In this case, even I can’t solve these problems. The support from the hardware and OS vendors is near non-existent. The forums are filled with dumbasses giving partial or incorrect answers. The OS doesn’t offer many clues. I’ve wasted far too much time searching for solutions.

Honestly, for most people Mac OSX is nothing special, except it Just Works. People spend 90% of their day in the browser anyway. Being able to walk into an Apple Store and have a “Genius” fix simple problems is a killer feature. AFAIK there is nothing comparable for Windows nor any consumer hardware vendor. Dell’s XPS support was never useful. Best Buy’s Geek Squad is a royal ripoff. ($70 to fix your email!) If Microsoft can’t entice hardware vendors to do a less shitty job they will continue to lose market share to simpler devices. The jury is still out on the Surface.

Google’s ChromeOS is the right idea, but still falls short. What can it do that can’t be done with a tablet + keyboard? Most people would rather get the latter. Some people still require extra software to connect to work and run work applications (like WebEx or Excel/PPT or VPNs). Those applications are ported to iOS/Android before ChromeOS. Also, the Chrome hardware is mostly $300 plastic garbage, plus the expensive Pixel.

Apple wins because their service is fantastic (IME), their hardware/OS combo Just Works, and OS X is good enough. Microsoft loses because even if Win10 were perfect, the service is abysmal and the hardware/OS combo is atrocious. The Surface might solve the last point. ChromeOS is in the middle because the hardware/OS just works, there is no service (AFAIK), and the OS might be just short of good enough for some people. A tablet + keyboard is better than ChromeOS for most people because iOS/Android has more apps.

Offline Google Drive without changing default browser

Google Drive supports offline access of your documents by running the little Google Drive sync tool. When you click on something, the Drive tool acts like a local web server and opens your default browser. However, this will only work if Chrome is your default browser. What if you want to use something else? I found this old script googledrivesync-chrome which appears to do the trick for Windows. Download the zip file, copy the files to C:\Program Files (x86)\Google\Drive, and run “googledrivesync-chrome.wsf /install”. I just tried it on Windows 10 and it seems to work.

Notes for Computer Security

I’m not a security expert. For a long time I used the same terrible password everywhere because I’m a lazy moron. But I finally cleaned up my act. The first thing to decide is who is my adversary. I’m not trying to protect myself against government agencies nor violent crime lords. In both cases they will merely cut off my fingers until I give up my password. I’m primarily worried about hackers grabbing passwords in bulk from web sites. I’m only a tiny bit concerned about hackers getting on my machine directly.

I used Diceware to come up with a 6 word password, which is about 77 bits. I then changed a few characters randomly. Each change adds another 10 bits. I wrote it down on paper and store it in my wallet. I use this as my master password for LastPass. In addition, I use 2 factor authentication (2FA) using Google Authenticator to generate login codes (TOTP). Using LastPass I’ve generated unique, big, complex passwords for all the sites I use. Basically, there’s no way for me to log into anything without LastPass. For important sites that support it, I use 2FA with Authenticator. For these same sites I generated backup codes and stored them as secure notes in LastPass.

I use LastPass app on my iPhone 5. It’s a pain to type in my master password, so I use a PIN code to protect it. I wish that LastPass copied the iPhone’s Erase Data option: after 10 failed attempts it should delete the LastPass encrypted file. For someone to get this data, they need to get through the iPhone PIN and the LastPass PIN. I should use a password instead of a simple 4 digit passcode on the iPhone.

On my Mac I use the LastPass browser extension and the LastPass desktop app. Neither of these are password protected, and I turned off 2FA. I can set them to auto logoff after a timeout, but then I have to type in my master password every time. I’d prefer to enter a PIN code, which falls back to the master password after 3 failures. Instead, the only thing protecting my computer is a terrible account password. I should change that. Again, I wish the Mac supported a PIN for quick login and a backup password. Or 2FA somehow.

My laptop is encrypted with FileVault. Backups run by Crashplan are encrypted with my account password. The spare computer holding my backups has a terrible password and is not encrypted. I think that’s all ok so far. Though I’m not sure why security people trust FileVault and not Microsoft’s BitLocker.

For some inexplicable reason, none of my banks — the most important sites to protect!! — support 2FA. Etrade does support Symantec’s VIP Access app. However, why don’t they support Authenticator or just plain TOTP? Also, if I turn it on then I can’t use Quicken or Mint.com. It should support app-specific passwords that have read-only access to my accounts. This is a serious weakness.

I really don’t like Google Authenticator. I’d prefer to use Authy. It’s easier to use and it stores an encrypted backup of your codes to load onto another phone. But I don’t quite understand how they ensure the other phone is under my control. Could a hacker fool them into copying my Authy data to another device? Plus, their desktop app doesn’t feel like it’s in the spirit of 2FA.

LastPass is the center of my security universe. If someone breaks into LastPass, as they did recently, I’m pretty much screwed. Other people use KeePass because they have control over the encrypted DB. But it isn’t easy to use like LastPass. It’s a tradeoff I’m willing to make. I’d like to use Yubikey when LastPass supports U2F. This would prevent phishing attacks. However, I’m still vulnerable if someone figures out how to write a page that extracts data from the browser extension. Also, I’m not comfortable with their account recovery schemes. I think there’s a way for an attacker to turn off 2FA and then force recovery using a OTP stored in your browser. This would work if they have your laptop, including email access. I should fix this somehow.

Overall this setup is moderately secure, but the NSA could break it in a jiffy.

3-way merge of PowerPoint with git

This doesn’t work for some reason, but I’ll make a note and look at it later. On the Mac’s Script Editor, the dictionary for MS PowerPoint 2011 says it has a method called mergeWithBaseline. That sounds like a 3-way merge. This is a sketch of what the code should look like. For some reason I can’t get mergeWithBaseline to do anything.

osascript -l JavaScript << EOF
PPT = Application("Microsoft PowerPoint");
local = Path($1)
PPT.activeWindow.presentation.mergeWithBaseline({withRevisionPath: $2, withBaselinePath: $3})
PPT.save({in: $4, as: "save as presentation"})

In the .gitconfig there should be something like this:

[mergetool "powerpoint"]
    cmd = pptmerge \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"

It looks like you can select different merge tools with “git mergetool –tool=powerpoint fileName”. Is there a way to trigger this by file extensions (.pptx)?