Viewing posts by davidkircos

End to End Testing for Expo Apps With CircleCI & Detox

It is becoming increasingly common for developers to begin to develop their apps with Expo with React Native. Expo is a great developer experience for getting started. However, some more advanced workflows for publishing production applications do not come out of the box. One of the missing workflows is end-to-end testing. So we set out to develop a method to run tests on our expo app using Continous Integration. Here is the configuration we came up with to successfully use CircleCI to test our Expo app using the testing framework Detox + Jest.

Below is our config.yml file. Our process works by performing the following steps:

  1. Install application dependencies.
  2. Log into the ExpoCLI using env vars (you have to set these in the CircleCI UI).
  3. Instruct Expo to do an iOS build with the target simulator.
  4. Download the build from Expo and extract it.
  5. Install testing packages.
  6. Run tests using detox test.


Here is a copy of our .detoxrc.json file

And here is our testing/config.json file

Our test runner takes about 10 minutes to set up and run a set of ~10 tests. The test setup is probably partially redundant and could be sped up. However, this works for us today! We hope this is helpful for you in setting up Expo End to End Testing!

Django + Postgres Views

Over the years, the Django ORM has become my go-to way to interact with a database from Python. It is an incredibly robust binding between the database and Python. As Postgres added advanced database features, the Django ORM kept up. An early example of this is Django's implementation of JSONB fields. The JSONB fields allowed you to save JSON as a field and interact with the JSON object's contents from the SQL query level. Django quickly supported this powerful feature. Awesome.

Another powerful feature added Postgres added is Views. Views are a simple database feature that allows you to create an alias for a common query. Suppose you were routinely running a SELECT statement on a table of transactions for the category outdoor_products:

SELECT * FROM tranactions_table WHERE product_type='outdoor'

In Postgres, you can save this query as a view for future reference.

CREATE OR REPLACE VIEW 'outdoor_product_transactions_view' AS 
(SELECT * FROM tranactions_table WHERE product_type='outdoor')
Then you can just
SELECT * FROM outdoor_product_transactions_view
And easily apply additional filters
SELECT * FROM outdoor_product_transactions_view WHERE amount > 1000

This feature is great for complex queries you are regularly repeating.

In the application I am currently building, there are complex queries that I run regularly on our API. I would also like our BI tools to benefit from these complex queries without repeating the logic in SQL. So I set out to create an easy way for a Django queryset to manage a Postgres view.

Here is the result:

from django.db import connection

def create_or_replace_view(view_name, view_qs):
    with connection.cursor() as cursor:
        queryset = view_qs
        compiler = queryset.query.get_compiler(using=queryset.db)
        sql, params = compiler.as_sql()
        sql = "CREATE OR REPLACE VIEW {view} AS {sql}".format(
            view=connection.ops.quote_name(view_name), sql=sql
        cursor.execute(sql, params)

from postgresviews.create_or_replace_view import create_or_replace_view
from ledger.querysets.formattedTransactionsQS import FormattedTransactionsQS

## Define Views Here
## NOTE: Renamed or Deleted Views will not automatically clean up the old version.
    "view_formatted_transactions", FormattedTransactionsQS().get_qs()
) is run on every deployment of our Django API. This allows me to use complex querysets with our API via Django Rest Framework and build a Postgres view of the queryset available to our BI tools. Magic! I hope you find this useful in your own applications!

Skiing Into the Night

This past Friday night my friend Marco Vienna and I started running up Mt. Crested Butte on skis at midnight in a bid over Star Pass to end up in Aspen. This route is 37 miles, part of a Ski Mountaineering race called The Grand Traverse. We estimated the trip would take us 12 hours. Our friend (and support team) Danni Perri took this photo before the start of the race. Thank you so much for the support Danni!

For the first 5 hours of the race, we were doing great. We made it over Death Pass with plenty of time to spare and were actively passing other participants. Yes, it is actually called Death Pass - 2 people died on this section of the route while training for the race this year. There was a memorial on the racecourse.

We were heading up a high elevation valley called the Brush Creek Drainage. It was about 5 degrees out and I felt warm because we had been moving non-stop. Around this time we stopped for a few minutes to eat and drink water. And I got cold. It's not clear exactly what happened but my best guess is that I contracted mild hypothermia in my lungs which from then on made it extremely difficult to breathe.

We continued for the next two hours towards the next checkpoint, but my pace was much slower. Around six and a half hours in, I could only move a dozen meters before being forced to stop and catch my breath. This was a demoralizing rhythm, but we continued up the mountain. We made it to the Friends Hut checkpoint about 10 minutes before the cutoff. This checkpoint is right before a difficult climb over Star Pass, followed by the most difficult descent of the route.

While the rules of the race would have let us continue, at this point, I was pretty worried about how difficult it was for me to breathe. And there was no way I would have felt safe taking myself and friend up the pass. If my condition worsened at all, it would have put us both in an unacceptable amount of danger. If I couldn't get down under my own power, it would have been bad.

It was disappointing not to finish. But I am so happy we were able to get out there and try something truly difficult for our ability. Right as we decided not to continue, the sun finally rose after 7 hours of skiing in the dark, and we were rewarded with this view. It was the best silver lining.

Last fall I dragged Marco to Aspen for the Mountain Bike version of the Grand Traverse and this Spring he dragged me to Crested Butte for the ski version. Continuing the tradition we will be running this route in the fall (kidding... hopefully)

How Convertible Notes Convert, Template

Convertible notes and SAFEs are great because they allow startups and investors to defer the difficult process of valuing an early stage company and quickly close funding. This is at the cost of putting the burden on later investors determine the value of the company, generally, once the company has more metrics to base a valuation on. With the convertible note holders getting some type of discount for investing early. If you want to read more about the mechanics of convertible notes I recommend Brad Feld's series of blog posts -> read here.

I've been involved with a number of companies who have raised multiple rounds of convertible note financings, without really understanding how all the rounds will convert when a priced round occurs. Over time I have developed a generic Google Sheet template which given a cap table and convertible note terms calculates Series A conversion scenarios providing insight on how everything will play out.

To access the template - > Click Here and go to File -> Download As an excel copy. From there you can re-upload the file to your own Google Drive.

In the first tab 'Pre-Investment Cap Table' add your current cap table. Usually only contains founders and maybe some early employees.

The tab 'Convertible Notes' is where you input your convertible notes. It is ok to leave either cap or discount blank. SAFE's can also be input in this sheet, they are functionally equivariant to convertible notes. Inputting multiple rounds of convertible notes here is also ok, just add them with different dates and terms.

The next tab 'Series A Inputs' is where you input a Series A scenario based on the pre-money valuation and round size. This sheet also allows you to calculate an employee option pool expansion concurrent with the Series A fundraising (this is common).

The final tab 'Series A Cap Table' shows both pre and post Series A cap tables side by side. Showing the effect of the convertible notes on the final cap table.

If you find this sheet valuable, please leave a comment. I am happy to take suggestions or discuss unique fundraising scenarios that don't fit in this template.

Why I Don't Actively Invest On Public Markets

I do not actively trade any stocks or bonds on the public markets. I've also avoided cryptocurrencies, which trade on a public market.

I avoid public market trading for a couple of reasons:
1) It's been empirically shown that holding a diversified portfolio of investments for a long period of time is a better strategy than attempting to identify individual stocks that will outperform the market. This is because any additional gains you get by actively trading, on average, will be canceled out by the value of the effort put into achieving those gains. This leaves you, the average person, no better off than just passively holding diversified investments over a long period of time. Weathfront has a great explanation of why this is the case: in this blog post.

2) It's stressful. At any given time you could be doing better if you had more information on the companies you are trading. At any given time you could be doing better if you buy and sell at just the right time. At any given time... When actively trading this constantly was in my head, I became obsessive about research. This was emotional stressful. While probably not applying to everyone, it is not worth the stress to me.

3) Success attribution. It's really difficult (or maybe impossible) to identify the signal of why certain stock picks performed well and why others performed poorly. Which would be necessary to consistently pick well-performing stocks.

If you want to be investing more of your money but don't know where to start, I recommend checking out Wealthfront. They give you very good diversification without any fees on your first $10k, they encourage good long-term thinking, and they are not paying me to say any of this. Investing is important to wealth building, and active investing is one of the traps many first time investors will get caught in.

It would be disrespectful not to mention Jack Bogle, founder of Vanguard investments, who pioneered bringing low cost diversified investment instruments to regular investors. Before Vanguard, if you wanted to match the performance of the S&P 500 you would need to buy every stock in the S&P 500. Vanguard created the first widely available index funds. By doing this Vanguard democratized access to index investing, by lowering the cost and complexity of making index investments. This gave regular people access to sophisticated investing techniques. What Wealthfront does is the modern continuation of these ideas, with added features such as Tax-Loss Harvesting and Automatic Rebalancing.