Avoiding Blackberry’S Fate – Marco.Org

The BlackBerry’s success came to an end not because RIM started releasing worse smartphones, but because the new job of the smartphone shifted almost entirely outside of their capabilities, and it was too late to catch u

Today, Amazon, Facebook, and Google are placing large bets on advanced AI, ubiquitous assistants, and voice interfaces, hoping that these will become the next thing that our devices are for.

If they’re right — and that’s a big “if” — I’m worried for Apple.

Marco makes a lot of good points and I agree with this 100%. The mobile phone market as we know it is primed for the "next big thing" by someone. Who that is, and whether they are right remains to be seen. Do I mean that the current market is stagnant, or that innovation is dead? Of course not. But, I do think changes we'll see from the big 2 to their platforms will be incremental. There will always be new UI paradigms, features, and apps that can augment a platform.

The next large improvement will be what our devices start DOING with the data we give them. Not just inputs and outputs. But contextually understanding the data and begin to make predictions on it. Apple is "good" at the former; give them something and they will give it back to you quickly. iMessage and the new photos are examples of this. Passwords, backups, and sync are examples of where they fall short. However, they can't act on that data. Photos knows who someone is because you tagged them. Or knows how much you liked a photo or a restaurant because you gave it stars. Input and outputs. Compare this to Google photos (which is downright amazing) that automatically just "knows" who is in the photo or figures out that an event took place because you traveled to it.

Google is king of data mining and context (Facebook and Amazon are not far behind). As Marco explains in his piece, Apple just can't catch up to that. It's my hope that the awesome that Google will bring in the form of Ai to devices won't be restricted to Android. I'm sure that Android will always have the most seamless experience, but it will be nice if Google's apps bring much of it to iPhone. Even better, would be for Google and Apple to get along again ala when Google Maps came installed on your iPhone

Setup and Teardown the Database Once Per Test Suite in PHPUnit

I'm working on a series of integration tests where I want to set up and reset the database for each run. This could easily be done in the setUp and tearDown methods, but doing the full db each time is slow. Yes, I could just do the tables I need, but I was curious, and now I don't have to worry about which tables are setup in my testing DB. In this example, I'm using Laravel's migrations and SQLite as the test DB.

UPDATE 05/05/2016: As Sebastian points out below (thanks!) there is a much more appropriate way. Using setUpBeforeClass and tearDownAfterClass we achieve the same effect

public static function setUpBeforeClass()
{
    parent::setUpBeforeClass();
    exec('php artisan migrate --database sqlite_test');
}

public static function tearDownAfterClass()
{
    exec('php artisan migrate:reset --database sqlite_test');
    parent::tearDownAfterClass(); 
}

PHPUnit has listeners that you can tap into at various parts of your tests' lifecycle. I'm particularly interested in when a specific suite starts and ends. We'll need to do 2 things:

  1. Create our Listener
  2. Register this Listener in phpunit.xml

The listener is as follows:

class FullDBListener extends PHPUnit_Framework_BaseTestListener
{
    protected $suites = ['UserIntegrationTest', 'AccountIntegrationTest'];

    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if (in_array($suite->getName(), $this->suites)) {
            exec('php artisan migrate --database sqlite_test');
        }
    }

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if (in_array($suite->getName(), $this->suites)) {
            exec('php artisan migrate:reset --database sqlite_test');
        }
    }
}

This does a few things:

  1. Stores the class names of each suite we want to run the db migrations for
  2. In startTestSuite it checks to see if we're in the right suite
  3. If we are, run an artisan migration on our test db
  4. In endTestSuite it checks to see if we're in the right suite
  5. If we are, run an artisan migration:reset on our test db

Next, we need to make PHPUnit aware of this listener. Update your path accordingly

<listeners>
    <listener class="FullDBListener" file="./tests/app/FullDBListener.php"></listener>
</listeners>

That's it!

I do do some basic teardown in my test suite's setUp method to give me a blank slate. This has proven faster then doing the migrations each time

public function setUp()
{
    parent::setUp();

    User::truncate();
}

I hope this helped you, if you have any questions, let me know!

Gtdjedi Podcast - Ep015 - Notes On Notes

Note Management & Organization

What kind of notes go where: images, text, bookmarks, photos?

Will we see services eventually go away as native solutions become more complete?

The importance of syncing and sharing

Note Widgets: Do you use them? Which ones & how?

Presenting Unanticipated Errors To Users

This is the start of a really great series. It uses Swift for the examples but everything in the articles holds true for any language/platform

First, some quick terminology:

  1. an error condition is a failed conditional check that results in a function skipping its usual functionality and instead returning an nominated error value.

  2. an error is a value used to report that an error condition occurred and normal functionality was skipped

  3. error handling is code that looks for errors and performs different actions based on the presence of those errors

  4. error reporting communicates an error result from a user task to the user

Trying to Mock a Self Booting Laravel Model Trait

Bootable Model traits are pretty nifty. I'm using them to register certain events for the models using my Trait. However, I've run into an issue trying to mock models that are using the trait. Specifically, when a Mockery version of the model is instantiated, it's boot code agrees that it should have a bootMyTrait method, but can't find it when it tries to call it.

Sample Repository for the below, with commands to reproduce.

As an example, here is a trait:

namespace App;
trait MyTrait
{
    public static function bootMyTrait()
    {
        print("Booting MyTrait\n");
    }
}

And a model using it:

namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
    use MyTrait;
}

Instantiating the model regularly works fine. This shows the desired output:

$model = new MyModel();

However, trying to mock this model does not cooperate. This:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;


class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $model = $this->getMock('App\MyModel');
    }
}

Fails. Adding some debugging to Eloquent:

    /**
     * Boot all of the bootable traits on the model.
     *
     * @return void
     */
    protected static function bootTraits()
    {
        $class = static::class;

        foreach (class_uses_recursive($class) as $trait) {
            print("\nTesting that class: $class has method: " . $method = 'boot'.class_basename($trait) . " because of Trait: $trait\n");
            if (method_exists($class, $method = 'boot'.class_basename($trait))) {
                print("Class: $class has method: $method \n");
                try {
                    forward_static_call([$class, $method]);
                } catch (\PHPUnit_Framework_MockObject_BadMethodCallException $e) {
                    print("Class: $class failed calling $method\n");
                    throw $e;
                }
            }
        }
    }

Gives us this failure:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)
Testing that class: Mock_MyModel_9ee820db has method: bootMyTrait because of Trait: App\MyTrait
Class: Mock_MyModel_9ee820db has method: bootMyTrait
Class: Mock_MyModel_9ee820db failed calling bootMyTrait


Time: 129 ms, Memory: 18.00Mb

There was 1 error:

1) ExampleTest::testTraitBooting
PHPUnit_Framework_MockObject_BadMethodCallException:

mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:326
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:309
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:296
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:277
mock-bootable-laravel-model-trait/tests/ExampleTest.php:16

I've also tried creating the mock a few different ways. Using DatabaseSoftDeletingTraitTest as an example:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel');
        $mock->shouldReceive('bootMyTrait')->once();
    }
}

But here, bootMyTrait is never called:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 149 ms, Memory: 19.25Mb

There was 1 error:

1) ExampleTest::testTraitBooting
Mockery\Exception\InvalidCountException: Method bootMyTrait() from Mockery_0_App_MyModel should be called
 exactly 1 times but called 0 times.

mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Expectation.php:271
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:297
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:282
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery.php:142
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:122

So, I can move the code I'm doing in the boot method to a ServiceProvider, but then I'll need to register each Model that uses the trait. This feels dirty, and using the boot method seems appropriate. So I think I've either hit a bug, or am Mocking the trait-using-model incorrectly. I've looked at getMockForTrait but I also need the mocked instance to extend Eloquent (a few of the trait's methods call eloquent methods)

If anyone sees something I missed, much appreciated

Update Apr, 22 (Friday) 2016-04-22 03:28 PM

Thanks to Marcin, we have a solution!

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel')->makePartial();
        $mock->shouldReceive('bootMyTrait')->once();
        $mock->__construct();
    }
}

Everything Is Possible But Nothing Is Free

What those asking really want to know, though, is one of two things:

Can you just build this thing I want, in addition to all the other things already on your plate, without moving any of your estimates?

Is this “easy” to do?

Here’s a simpler approach: I would like to have this and I’m willing to pay up to that.

Gtdjedi Podcast - Ep014 - Getting Social

The Big Discussion

Social Networking

Which services we use

Which services manage which relationships

Which services we stay away from

What routines are in place that help keep our circles and feeds streamlined

What does it take for a social network to have staying power on your devices?

Jedi Weapons of Choice

Clay - Tweetbot

Jerry - Facebook Paper

Tim - Cluster