Giter Club home page Giter Club logo

testdummy's Introduction

TestDummy Build Status SensioLabsInsight

TestDummy makes the process of preparing factories (dummy data) for your integration tests as easy as possible. As easy as...

Build a Post model with dummy attributes.

use Laracasts\TestDummy\Factory;

$post = Factory::build('Post');

If we then do $post->toArray(), this might return:

array(4) {
  ["title"]=>
  string(21) "The Title of the Post"
  ["author_id"]=>
  string(1) "5"
  ["body"]=>
  string(226) "Iusto qui optio et iste. Cumque aliquid et omnis enim. Nesciunt ad esse a reiciendis expedita quidem veritatis. Nostrum repellendus reiciendis distinctio amet sapiente. Eum molestias a recusandae modi aut et adipisci corrupti."
  ["publish_date"]=>
  string(19) "2014-03-02 11:05:48"
}

Build a post, but override the default title.

use Laracasts\TestDummy\Factory;

$post = Factory::build('Post', ['title' => 'Override Title']);

Again, when cast to an array...

array(4) {
  ["title"]=>
  string(14) "Override Title"
  ["author_id"]=>
  string(1) "5"
  ["body"]=>
  string(254) "In eos porro qui est rerum possimus voluptatem non. Repudiandae eaque nostrum eaque aut deleniti possimus quod minus. Molestiae commodi odit sunt dignissimos corrupti repudiandae quibusdam quo. Autem maxime tenetur autem corporis aut quis sint occaecati."
  ["publish_date"]=>
  string(19) "2013-06-24 10:01:30"
}

Build an array of attributes for the model.

$post = Factory::attributesFor('Post');

The difference between build() and attributesFor() is that the former will return an instance of the given model type (such as Post). The latter will simply return an array of the generated attributes, which can be useful in some situations.

Build and persist a song entity.

use Laracasts\TestDummy\Factory;

$song = Factory::create('Song');

Create and persist a comment three times.

use Laracasts\TestDummy\Factory;

Factory::times(3)->create('Comment');

In effect, this will give you three rows in your comments table. If that table has relationships (such as an owning Post), those related rows will be created with dummy data as well.

Usage

Step 1: Install

Pull this package in through Composer, just like any other package.

"require-dev": {
    "laracasts/testdummy": "~2.0"
}

Step 2: Create a Factories File

TestDummy isn't magic. You need to describe the type of data that should be generated.

Within a tests/factories directory, you may create any number of PHP files that will automatically be loaded by TestDummy. Why don't you start with a generic tests/factories/factories.php file.

Each factory file you create will automatically have access to two variables:

  • $factory
  • $faker

$factory is the function that you'll use to define new sets of data, such as the makeup of a Post or Album.

$factory('Album', [
    'name' => 'Rock or Bust',
    'artist' => 'AC/DC'
]);

Think of this as your definition for any future generated albums - like when you do this:

use Laracasts\TestDummy\Factory;

$album = Factory::create('Album');

Faker

You probably won't want to hardcode strings for your various factories. It would be easier and faster to use random data. TestDummy pulls in the excellent Faker library to assist with this.

In fact, any files in your tests/factories/ directory will automatically have access to a $faker object that you may use. Here's an example:

$factory('Comment', [
    'body' => $faker->sentence
]);

Now, each time you generate a new comment, the body field will be set to a random sentence. Refer to the Faker documentation for a massive list of available fakes.

Relationships

If you wish, TestDummy can automatically generate your relationship models, as well. You just need to let TestDummy know the type of its associated model. TestDummy will then automatically build and save that relationship for you!

Using the Comment example from above, it stands to reason that a comment belongs to a user, right? Let's set that up:

$factory('Comment', [
    'user_id' => 'factory:User',
    'body' => $faker->sentence
]);

That's it! Notice the special syntax here: "factory:", followed by the name of the associated class/model.

To illustrate this with one more example, if a song belongs to an album, and an album belongs to an artist, then we can easily represent this:

$factory('App\Song', [
    'album_id' => 'factory:App\Album',
    'name' => $faker->sentence
]);

$factory('App\Album', [
    'artist_id' => 'factory:App\Artist',
    'name' => $faker->word
]);

$factory('App\Artist', [
    'name' => $faker->word
]);

So here's the cool thing: this will all work recursively. In translation, if you do...

use Laracasts\TestDummy\Factory;

$song = Factory::create('App\Song');

...then not only will TestDummy build and persist a song to the database, but it'll also do the same for the related album, and its related artist. Nifty!

Custom Factories

So far, you've learned how to generate data, using the name of the class, like App\User. However, sometimes, you'll want to define multiple types of users for the purposes of testing.

While it's true that you can use overrides, like this:

Factory::create('App\User', ['role' => 'admin']);

...if this is something that you'll be doing often, create a custom factory, like so:

// A generic factory for users...

$factory('App\User', [
    'username' => $faker->username,
    'password' => $faker->password,
    'role'     => 'member'
]);

// And a custom one for administrators

$factory('App\User', 'admin_user', [
    'username' => $faker->username,
    'password' => $faker->password,
    'role'     => 'admin'
]);

In the code snippet above, you're already familiar with the first example. For the second one, notice that we've added a "short name", or identifier for this special type of user factory. Now, whenever you want to quickly generate an admin user, you may do:

use Laracasts\TestDummy\Factory;

$adminUser = Factory::create('admin_user');

Defining with Closures

Alternatively, you may pass a closure as the second argument to the $factory method. This can be useful for situations where you need a bit more control over the values that you assign to each attribute. Here's an example:

$factory('App\Artist', function($faker) {
    $name = sprintf('Some Band Named %s', $faker->word);
    
    return [
        'name' => $name
    ];
});

Of course, just be sure to return an array from this closure. If you don't, an exception will be thrown.

Step 3: Setup

When testing against a database, it's recommended that each test works with the exact same database environment and structure. That way, you can protect yourself against false positives. An SQLite database (maybe even one in memory) is a good choice in these cases.

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

    Artisan::call('migrate');
}

Or, if a DB in memory isn't possible, to save a bit of time, a helper Laracasts\TestDummy\DbTestCase class is included with this package. If you extend it, before each test, your test DB will be migrated (if necessary), and all DB modifications will be channelled through a transaction, and then rolled back on tearDown. This will give you a speed boost, and ensure that all tests start with the same database structure.

use Laracasts\TestDummy\DbTestCase;

class ExampleTest extends DbTestCase {

    /** @test */
    function it_does_something()
    {
        // Before each test, your database will be rolled back
    }
}

Step 4: Write Your Tests

You're all set to go now. Start testing! Here's some code to get you started. Assuming that you have a Post and Comment model created...

use Laracasts\TestDummy\Factory;

$comment = Factory::create('Comment');

This will create and save both a Comment, as well as a Post record to the database.

Or, maybe you need to write a test to ensure that, if you have three songs with their respective lengths, when you call a getTotalLength method on the owning Album model, it will return the correct value. That's easy!

// create three songs, and explicitly set the length
Factory::times(3)->create('Song', ['length' => 200]);

$album = Album::first(); // this will be created once automatically.

$this->assertEquals(600, $album->getTotalLength());

Now, of course, just make sure that you've registered a definition for a Song and Album in one of your factory files, and you're good to go!

// tests/factories/factories.php

$factory('Song', [
  'album_id' => 'factory:Album',
  'name' => $faker->sentence
]);

$factory('Album', [
  'name' => $faker->sentence
]);

FAQ

How do I specify a different factories folder?

Easy. Before your tests run, add:

Factory::$factoriesPath = 'app/tests/factories';

Now, TestDummy will look for your registered factories in the app/tests/factories folder.

I want to control how my models are built and saved...

Okay, just create your own implementation of Laracasts\TestDummy\IsPersistable. This contract is composed of a few methods that you'll need to implement.

Once you have your implementation, before your tests run, add:

Factory::$databaseProvider = new MyCustomBuilder;

And that's it! Now, whenever you generate and save an entity, TestDummy will reference your custom implementation.

testdummy's People

Contributors

adamwathan avatar antonioribeiro avatar brandonwiele avatar devinfd avatar dwightwatson avatar erictendian avatar hardevine avatar jeffreyway avatar jeroennoten avatar jwalton512 avatar kbirmhrjn avatar robmazur avatar swekaj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

testdummy's Issues

[2.0] Recursion error when factory creates relationship on itself

TestDummy is unable to handle creating a dummy record when the record requires a mock of itself for a relationship.

An example:

A User model can must be created by a user (think of a customer relationship management system, a new customer contact record is created, but the business wants to log who has created, or owns that user account).

The following code can be used to replicate the issue:

$factory('App\User', [
    'uuid'      => $faker->uuid,
    'name'      => $faker->name,
    'email'     => $faker->email,
    'created_by_id' => 'factory:App\User'
]);

Ideally, if there is only one User being created that has a self relationship, it should set the id the the id that has been inserted.

'Object of class Closure could not be converted to string' when mixing $factory and string in configuration

This is my first day working with TestDummy so let me know if there is a better way to accomplish what I'm trying.

I'm looking to use TestDummy to generate random data, but to have a little bit of control over the output. For a Venue entity, instead of using $factory->sentence to get nonsense, I'd like to make use of Faker's abilities and get names like:

Bobby's Bar
Susan's Grille

I can do this without a problem when using faker straight up

echo "{$faker->firstName}'s {$faker->randomElement(['Bar', 'Grille'])};"

but when I try using TestDummy I get the error

'Object of class Closure could not be converted to string'

I'm trying

$factory('Venue', [
    'name'=>$faker->firstName . "'s "
]);

but the concatenating makes the tool get angry.

L5 Model not replaced by table name

I am trying to implement TestDummy using L5 but it seems like the table name is replaced by the model.
I maybe doing something wrong in my L5 implementation or this maybe a bug.

Illuminate\Database\QueryException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.App\Repositories\User\User' doesn't exist (SQL: select * from `App\Repositories\User\User` where `email` = [email protected] and `first_name` = Test Name and `last_name` = Last Name limit 1)

The {type} model was not found.

I am trying to load the basic testdummy as follows

<?php
                Factory::$factoriesPath = base_path() . '/tests/factories';
        $userAttributes = Factory::build('User');
        return $userAttributes;

and my tests/factories/users.php file is as follows:

<?php
    $factory('User', [
        'first_name' => $faker->firstName,
        'last_name' => $faker->lastName,
        'email' => $faker->unique()->email,
        'password' => $faker->password,
        'gender' => $faker->randomElement(['Male', 'Female']),
        'activated' => $faker->boolean
    ]);

but when i run, it gives me error
The User model was not found.

does anyone knows what this is?

rand() always returns the same value in a $factory function

Considering the following code in my factories.php file:

$factory('App\Event', [

'title' => $faker->sentence(8),
'user_id' => rand(1,10),
'description' => $faker->sentence,
'address' => $faker->address,
'date' => $faker->date,
'time' => $faker->time

]);

When I do 'php artisan db:seed' , I get the same integer value for all events table entries on 'user_id'.

Overwrite relationship values

Hi Jeffrey,

Thank you for this wonderful library.
Is there a way to specify the value for a column of a relationship. By example, If a create('Token') it will automatically create the User associated with it but I wish this automatically created User to have a column of Active set to 0.

By any chance could do something like:

Factory::times(2)->create('Token', ['User' => ['active' => 0], 'secret' => 1234 ]);

Thank you,
Cheers.

Problem generating fake DateTime with MS SQL Server

When i specify in fixtures.yml a field like
created_at: $date

i get following errors:

InvalidArgumentException: Data missing

#1  D:\.....\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:2547
#2  D:\.....\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:2479
#3  D:\.....\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:407
#4  D:\.....\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:249
#5  D:\.....\vendor\laracasts\testdummy\src\Laracasts\TestDummy\EloquentDatabaseProvider.php:31
#6  D:\.....\vendor\laracasts\testdummy\src\Laracasts\TestDummy\Builder.php:100
#7  D:\.....\vendor\laracasts\testdummy\src\Laracasts\TestDummy\Builder.php:149
#8  D:\.....\vendor\laracasts\testdummy\src\Laracasts\TestDummy\Builder.php:117
#9  D:\.....\vendor\laracasts\testdummy\src\Laracasts\TestDummy\Factory.php:61
#10 D:\.....\tests\_support\FunctionalHelper.php:12

What it comes down to is that fake data looks like 'created_at' => string(19) "2014-04-02 18:19:52"
But unlike DateFormat 'Y-m-d H:i:s' from Database\Grammar.php, Illuminate\Database\Query\Grammars\SqlServerGrammar::getDateFormat() returns 'Y-m-d H:i:s.000'
and
DateTime::createFromFormat('Y-m-d H:i:s.000', "2014-04-02 18:19:52")
returns false;

I am not sure how to proceed. Not even sure who is in the wrong here: me? TestDummy? Carbon? Eloquent?

Many-to-many relationships?

I know I can do the below example for a one-to-many relationship in TestDummy.

Post:
  title: Hello World $string
  body: $text
  published_at: $date
  author_id:
    type: Author

Author:
    name: John Doe $integer

But how do I do a many-to-many relationship? This requires defining a pivot table, which I can't define in the fixtures.yml file.

Non standard id name field

I have a database which uses different id names for the primary key, like iduser, and not the standard user_id, this makes TestDummy not recognize this part in the fixtures file:

iduser:
type: Ghi\Users\User

ErrorException: preg_replace(): Parameter mismatch, pattern is a string while replacement is an array

is there another way to make testdummy to create a model when the name of the field is not in format model_id??

Class 'Symfony\Component\Yaml\Yaml' not found

I get the following error when I attempt to call the factory class.

PHP Fatal error:  Class 'Symfony\Component\Yaml\Yaml' not found in /home/abhshkdz/projects/org/api/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php on line 84
PHP Stack trace:
PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/php/PHPUnit/TextUI/Command.php:130
PHP   4. PHPUnit_TextUI_TestRunner->doRun() /usr/share/php/PHPUnit/TextUI/Command.php:192
PHP   5. PHPUnit_Framework_TestSuite->run() /usr/share/php/PHPUnit/TextUI/TestRunner.php:325
PHP   6. PHPUnit_Framework_TestSuite->run() /usr/share/php/PHPUnit/Framework/TestSuite.php:705
PHP   7. PHPUnit_Framework_TestSuite->runTest() /usr/share/php/PHPUnit/Framework/TestSuite.php:745
PHP   8. PHPUnit_Framework_TestCase->run() /usr/share/php/PHPUnit/Framework/TestSuite.php:772
PHP   9. PHPUnit_Framework_TestResult->run() /usr/share/php/PHPUnit/Framework/TestCase.php:751
PHP  10. PHPUnit_Framework_TestCase->runBare() /usr/share/php/PHPUnit/Framework/TestResult.php:649
PHP  11. TestCase->setUp() /usr/share/php/PHPUnit/Framework/TestCase.php:801
PHP  12. Laracasts\TestDummy\Factory::create() /home/abhshkdz/projects/org/api/app/tests/TestCase.php:28
PHP  13. Laracasts\TestDummy\Factory::getInstance() /home/abhshkdz/projects/org/api/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php:59
PHP  14. Laracasts\TestDummy\Factory::setFixtures() /home/abhshkdz/projects/org/api/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php:32

Any suggestions?

Missing argument 2 for Laracasts\TestDummy\FactoriesLoader::{closure}()

[ErrorException]                                                         
Missing argument 2 for Laracasts\TestDummy\FactoriesLoader::{closure}() 

This error seems to be thrown despite no changes in relevant code.

My factory:

$factory('App\User', function($faker, $overrides) {
    $created = $faker->dateTimeBetween('-2 years', 'now');

    return [
        'username' => $faker->userName,
        'friendly_name' => $faker->firstName,
        'email' => $faker->safeEmail,
        'created_at' => $created,
        'last_login' => $faker->dateTimeBetween($created, 'now'),
    ];
});

My seed:

use Illuminate\Database\Seeder;
use Laracasts\TestDummy\Factory;

class UserTableSeeder extends Seeder {

    public function run()
    {
        DB::table('users')->delete();
        Factory::times(200)->create('App\User');
    }
}

Not Creating The Object

Im not sure if this is a problem or not but a Factory I am creating is not being created but also not throwing any errors.

Here is the code:

<?php namespace unit\repositories;

use Acme\Models\Hotel;
use App;
use Acme\Support\BaseTest;
use Faker\Factory;

class HotelTest extends BaseTest {

    /** @test */
    public function it_gets_a_hotel_by_the_partner_id()
    {
        Factory::create('Acme\Models\Hotel');

        $repo = App::make('Acme\Repositories\HotelRepository');

        $hotel = $repo->getByPartner(1);

        dd(Hotel::all());

        $this->assertInternalType('object', $hotel);
    }

}

The dd output is

class Illuminate\Database\Eloquent\Collection#805 (1) {
  protected $items =>
  array(0) {
  }
}

The fixture is in place as well.

I have other working tests no problem which makes this seem strange.

1.2 -> 1.3.2 update

Everything works fine on 1.2 but after the update when running the test suite I get this

  1. RecipeRepositoryTest::it_returns_a_recipe_from_slug
    BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::boot()

When doing
Factory::times(6)->create('App\Recipes\Recipe');
Or
$recipe = Factory::create('App\Recipes\Recipe');

My hunch is It's this commit 53fff1e?w=0

Faker not returning new randomized data

The following code throws constraint violations on email and username, but works when only 1 row is generated:

$factory('App\User', function($faker) {
    $created = $faker->dateTimeBetween('-2 years', 'now');

    return [
        'username' => $faker->userName,
        'friendly_name' => $faker->firstName,
        'email' => $faker->safeEmail,
        'created_at' => $created,
        'last_login' => $faker->dateTimeBetween($created, 'now'),
    ];
});

Seems like it isn't generating a new value on each faker call...?

[PHPUnit_Framework_ExceptionWrapper] The path provided for the factories directory, tests/factories, does not exist.

I've created my factories.php file in app/tests/factories directory and still get the error. After a little digging I found that I can provide the path in Factory::$factoriesPath. This isnt very convenient considering that I need to set this for each test. I think modifying the FactoriesLoader::assertThatFactoriesDirectoryExists() should probably check inside app_path() instead of is_dir. At the very least provide a config file where we can specify factories location as well as package namespace for classes.

I am on Laravel 4.1 using Codeception PHP Testing Framework v2.0.0 Powered by PHPUnit 4.5.0.

Table name from where is derived?

Hi Jeffrey, building the Larabook app, I realized that TestDummy fetch the data from statuses table. But I'm wondering from where it picks up that name, when the model is called status.

Could you please point me from where you get the table name to create a status record on the database?

Thanks in advance,
Esteve.

How to make a field required? Skipping a field when creating object?

I am not sure why this is failing, but it is. Here is my fixture for the contact table

Contact:
last_name: $string
first_name: $string
email: $string@$string.com
active: $boolean
companies_id:
type: Company
user_id:
type: User

When it generates the test object, the SQL produces an error

Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 contacts.first_name may not be NULL (SQL: insert into "contacts" ("last_name", "email", "active", "companies_id", "user_id", "updated_at", "created_at") values (consequatur, [email protected], 0, 1, 2, 2014-10-30 15:32:05, 2014-10-30 15:32:05))

Not quite sure why "first_name" field is being skipped. Is there a way in which I can mark the field as required?

Forced to pre-define nullable fields or fields with default values

I noticed that TestDummy ignores any overrides I set if I am not overriding a key that's predefined in a factory. I think this is unwanted behaviour.

// In the migration...
$table->string('bar')->nullable();

// In the factories file
$factory('Foo', []);

// In a test
$foo = Factory::create('Foo', ['bar' => 'baz']);
$foo->bar; // null, expected 'baz'

A basic factory should only define the fields that are absolutely required for the model to save to the database, so that you can easily create a model in a test and only specify the fields that matter to that test. Having to specify fields that the database will assign a default value for is unnecessary IMO.

The work around at the moment is to manually set any nullable fields to NULL, or fields with default values to the default value set in the schema. I think this introduces a maintainability risk, because if the default values in your factories get out of sync with the default values in your database, your tests run the risk of no longer being accurate.

What do you think? As far as I can tell it's as easy as swapping out this line:

https://github.com/laracasts/TestDummy/blob/master/src/Laracasts/TestDummy/Builder.php#L148

...for this:

return array_merge($factory, $attributes);

Factory Girl is the defacto standard for this sort of library and they've opted to go the path I've suggested here. I think it's probably best to lean on their experience and decisions for behaviours like this personally.

Error on installation with Composer

Your requirements could not be resolved to an installable set of packages.                                                                           

  Problem 1                                                                                                                                          
    - laracasts/testdummy 2.0.9 requires fzaninotto/faker ~1.4 -> no matching package found.                                                         
    - laracasts/testdummy 2.0.8 requires fzaninotto/faker ~1.4 -> no matching package found.                                                         
    - laracasts/testdummy 2.0.7 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.6 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.5 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.4 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.3 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.2 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0.11 requires fzaninotto/faker ~1.4 -> no matching package found.                                                        
    - laracasts/testdummy 2.0.10 requires fzaninotto/faker ~1.4 -> no matching package found.                                                        
    - laracasts/testdummy 2.0.1 requires illuminate/support ~5.0 -> no matching package found.                                                       
    - laracasts/testdummy 2.0 requires illuminate/support ~5.0 -> no matching package found.                                                         
    - Installation request for laracasts/testdummy ~2.0 -> satisfiable by laracasts/testdummy[2.0, 2.0.1, 2.0.10, 2.0.11, 2.0.2, 2.0.3, 2.0.4, 2.0.5,
2.0.6, 2.0.7, 2.0.8, 2.0.9].                                                                                                                         

Laracasts\TestDummy\TestDummyException: Could not locate a factory with the name: Larabook\Users\User

// PoststatusCept.php

am('a Larabook member'); $I->wantTo('I want to post statuses to my profile.'); $I->signIn(); $I->amOnPage('statuses'); $I->postAStatus('My first post!'); $I->seeCurrentUrlEquals('/statuses'); $I->see('My first post!'); # // this my functionalhelper.php haveAnAccount(compact('username', 'email', 'password')); $I = $this->getModule('Laravel4'); $I->amOnPage('/login'); $I->fillField('email', $email); $I->fillField('password', $password); $I->click('Sign In'); } // Fill out the publish status form. @param $body public function postAStatus($body){ $I = $this->getModule('Laravel4'); $I->fillField('body', $body); $I->click('Post Status'); } // Create a Larabook user account in the database. // @param array $overrides @return mixed public function haveAnAccount($overrides = []){ return $this->have('Larabook\Users\User', $overrides); } // Insert a dummy record into a database table. // @param $model @param array $overrides @return mixed public function have($model, $overrides = []){ return TestDummy::create($model, $overrides); } ``` }

override relationship when there is more then one.

HI Ive got a contract Entity that have two relationships the contract model is related to a advertiser as a advertiser can have many contracts , I also need to track which of our sales reps sold the contract so i have a sold_by column that is the id of the user who sold the contract so Its also a relationship now I created a factory which defines both.

$factory('Apps4u\Sharples\Models\Contract',
    [
        'contract_number' => $faker->numberBetween(10000, 99999),
        'sign_date' => $faker->date(),
        'total' => $faker->randomFloat(),
        'deposit' => $faker->randomFloat(),
        'payment_plan' => '50/50',
        'advertiser_id' => 'factory:Apps4u\Sharples\Models\Advertiser',
       'sold_by' => 'factory:Platform\Users\Models\User',

]);

Now when creating the data I override the advertser_id as I want it set the existing record as I have lots of relationships include lots of Polymorphic ones. but when I override the advertiser id but not the userid I get a error saying it can not insert advertiser_id into the users table (there is no link like that). so I can only override a value if I override both relationships.

I create a route to test my seed loading Ive use foreach loops so I can attach polymorphic relationships. As you can see Im override both sold_by (user id) and advertiser_id. But If I only override the advertiser_id I get a error saying that insert into user table failed table dose not have column advertiser_id . Which is correct so I dont know why its trying to do that.

function seed1() {
    Factory::$factoriesPath = base_path() . '/tests/factories';


Factory::times(50)->create('Apps4u\Sharples\Models\Contact');
Factory::times(50)->create('Apps4u\Sharples\Models\Call');
Factory::times(50)->create('Apps4u\Sharples\Models\Site');
Factory::times(50)->create('Apps4u\Sharples\Models\Comment');

$sites = Apps4u\Sharples\Models\Site::all();
$calls = Apps4u\Sharples\Models\Call::all();
$contacts = Apps4u\Sharples\Models\Contact::all();
$comments =  Apps4u\Sharples\Models\Comment::all();

$x = 0;
foreach ($sites as $site) {
    $site->calls()->save($calls[$x]);
    $site->contacts()->save($contacts[$x]);
    $site->comments()->save($comments[$x]);
    $x++;
}

}

function seed2() {
Factory::$factoriesPath = base_path() . '/tests/factories';
Factory::times(50)->create('Apps4u\Sharples\Models\Advertiser');
Factory::times(50)->create('Apps4u\Sharples\Models\Contact');
Factory::times(50)->create('Apps4u\Sharples\Models\Call');
Factory::times(50)->create('Apps4u\Sharples\Models\Comment');

$advertisers =  Apps4u\Sharples\Models\Advertiser::all();
$calls =  Apps4u\Sharples\Models\Call::all();
$contacts =  Apps4u\Sharples\Models\Contact::all();
$comments =  Apps4u\Sharples\Models\Comment::all();

$x = 0;
foreach ($advertisers as $advertiser) {
    $advertiser->calls()->save($calls[$x]);
    $advertiser->contacts()->save($contacts[$x]);
    $advertiser->comments()->save($comments[$x]);
    // create a new contract but not with new advertiser used on of just created advertisers.
    Factory::create('Apps4u\Sharples\Models\Contract', ['advertiser_id' => $advertiser->id, 'sold_by' => 1]);
    $x++;
}
return 'done';

}

Model boot() being ignore when updating model

I'm using Codeception to test a user repository I'm building. I'm having an issue with one of my tests:

// DbUserRepositoryTest
public function testSetPassword()
{
    $user = Factory::create("App\Models\User");
    $user = $this->repo->setPassword($user, "randompassword");
    $this->assertTrue(Hash::check("randompassword", $user->password)); 
}

// DbUserRepository
public function setPassword(User $user, $password) 
{
    $user->password = $password;
    $user->password_confirmation = $password;
    $user->save();

    return $user;
}

I have a base model that validates the attributes on save. If the password and password_confirmation pass validate I unset the password_confirmation attribute so that that system doesn't try and save it to the database (obviously there is no password_confirmation column, it's just used for validation).

Creating a little test route returns the results I expect:

Route::get('testing', function() {
    $repo = App::make("App\Repositories\Users\UserRepositoryInterface");
$user = App\Models\User::find(5712);
$user = $repo->setPassword($user, "randompassword");
dd(Hash::check("randompassword", $user->password)); // True
});

However my test fails. I get this error:

[PHPUnit_Framework_ExceptionWrapper] SQLSTATE[HY000]: General error: 1 no such column: password_confirmation (SQL: update "users" set "password" = randompassword, "password_confirmation" = randompassword, "updated_at" = 2014-11-13 11:42:01 where "id" = 1)

From what I can tell the validation method in my base model and static::saving function that runs it aren't firing at all when I run my test.

Is TestDummy not extending the models it's faking? Does anyone have any idea how I can resolve this issue?

Could not locate the fixtures.yml file.

Hi,

I have created a fixtures.yml file in the app/tests/ directory but I am getting the error "Could not locate the fixtures.yml file."

I looks like it is locating the file in the tests path based in the root folder instead of the app folder since first looking for a tests directory in the base path directory.

Best regards,
Ronnie Visser

Issue creating multiple related resources

Using the following fixture, TestDummy will only create the first relation it finds, the subsequent relation(s) are skipped:

Contact:
  first_name: $string
  last_name: $string
  email: $string@$string.com
  active: $boolean
  companies_id:
    type: Company
  user_id:
    type: User

When executing TestDummy::create('Contact') the following error is generated

Illuminate\Database\QueryException: 
SQLSTATE[23000]: Integrity constraint violation: 19 contacts.user_id may not be NULL 
(SQL: insert into "contacts" ("companies_id", "salutation", "first_name", "last_name", "email", "phone", "active", "updated_at", "created_at") 
values (1, Prof., Sonia, Homenick, [email protected], 1-616-460-0515x5448, 1, 2014-10-31 18:02:35, 2014-10-31 18:02:35))

Usage within packages

TestDummy currently cannot be used within packages easily for a number of reasons:

namespacing within DbTestCase.php refers to several items that are available only in the Laravel global namespace and available when testing from a package.

use TestCase, Artisan, DB;

Setting the $factoriesPath static attribute on Factory is not possible before the .../tests/factories/someFile.php is processed. Producing a Undefined variable: factory notice.

I may be approaching this wrong.

Exception: The {name} model was not found

I use artisan tinker as follows:

use Laracasts\TestDummy\Factory;
$factory = new Factory();
$factory->build('Comment');

As a result, I get TestDummyException with message 'The Comment model was
not found.'
I checked $factory->factories() and it clearly says that factory with name: 'Comment' is included. Issue happened for any other factory I used.

Problem of Duplicate entry

I'm Learning the lesson "21.Browsing Users With Pagination" of laracasts.
When I run UserRepositoryTest, I some times get a failure. it tells me: Duplicate entry username or email.

1) UserRepositoryTest::it_paginates_all_users
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'quia' for key 'users_username_unique' (SQL: insert into `users` (`username`, `email`, `password`, `created_at`, `updated_at`) values (quia, [email protected], y$JZayLEON7qjipeooyaillOey6L1AHPidyXmsXRzbTyLpganKINEsK, 2013-11-19 20:17:46, 2014-05-04 21:07:12))

Field skipped when creating object?

I have a fixture as:

Contact:
last_name: $string
first_name: $string
email: $string@$string.com
active: $boolean
companies_id:
type: Company
user_id:
type: User

When it generates the test object, the SQL produces an error (see first_name field is skipped)

Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 contacts.first_name may not be NULL (SQL: insert into "contacts" ("last_name", "email", "active", "companies_id", "user_id", "updated_at", "created_at") values (consequatur, [email protected], 0, 1, 2, 2014-10-30 15:32:05, 2014-10-30 15:32:05))

Overriding attributes for relationships

A few months back PR #52 was merged in which allowed overriding attributes for relationships.

Given these factories:

$factory('Post', 'post', [
    'title' => $faker->word,
    'body' => $faker->sentence
]);
$factory('Comment', 'comment_with_post', [
    'post_id' => 'factory:post'
    'comment' => $faker->sentence
]);

...you could create a Comment like so and specify the Post body simultaneously:

$comment = Factory::create('comment_with_post', [
    'comment' => 'First!',
    'body' => 'example'
]);

The flat nature of the attributes has led to some conflicts with other features like #65.

The issue is that this syntax provides no distinction between attributes that are meant for the Comment and attributes that are meant for the Post, so the entire attribute set is passed to both objects, meaning it tries to set the comment field on the Post and the body field on the Comment, even though those objects don't have those fields.

It creates more issues when two objects have a property of the same name, because now they will always have the same value and can't be set independently.

I'm opening this issue to start a discussion about an improved, explicit syntax that will allow this feature without the existing problems.

Two ideas I've had so far:

  1. Dot notation

    Use dot notation to scope the related attributes.

    $comment = Factory::create('comment_with_post', [
        'comment' => 'First!',
        'post.body' => 'example'
    ]);

    The string before the dot matches the name of the factory you are using for the relationship. So Post if you are using an unnamed factory, or post if you gave the factory an explicit name.

    The nice part about using a dot is that it's not a valid character in an object property, so it's very safe to treat any attributes containing dots as meant for relationships. It should be straightforward to make this work for nested relationships as well, like post.author.name.

    This is a decent simple solution but has limited flexibility if you ever have 2 relationships to the same factory, because there's no way to use separate attributes for each.

    Nevertheless, the value of handling that scenario might be lower than the value of using a simple syntax like this.

  2. Nested attributes

    This one is trickier and I don't have a great syntax for it yet, but perhaps something like this.

    $comment = Factory::create('comment_with_post', [
        'comment' => 'First!',
        'post_id' => [
            ':factory' => 'post',
            'body' => 'example'
        ]
    ]);

    This sort of approach is the most flexible but is tough to do nicely with arrays.

I think I like option 1 better despite the limited flexibility, but let's figure out if there's a better syntax.

How to use Faker languageCode?

Faker\Provider\Miscellaneous

boolean($chanceOfGettingTrue = 50) // true
md5                     // 'de99a620c50f2990e87144735cd357e7'
sha1                    // 'f08e7f04ca1a413807ebc47551a40a20a0b4de5c'
sha256                  // '0061e4c60dac5c1d82db0135a42e00c89ae3a333e7c26485321f24348c7e98a5'
locale                  // en_UK
countryCode             // UK
languageCode            // en

How can I use any one of these in fixtures.yml?

I have tried:

Language:
  locale: $languageCode

But it does not work. Any ideas ?

Versions 1.2 and up only support Laravel 5?

Simply put: laracasts/TestDummy ~1.2 and ~1.3 requires illuminate/support ~5.0, which throws dependency errors if using Laravel 4.2.x.

After composer install using "laracasts/testdummy": "~1.2":

Problem 1
    - laracasts/testdummy 1.3.3 requires illuminate/support ~5.0 -> no matching package found.
    - laracasts/testdummy 1.3.2 requires illuminate/support ~5.0 -> no matching package found.
    - laracasts/testdummy 1.3.1 requires illuminate/support ~5.0 -> no matching package found.
    - laracasts/testdummy 1.3 requires illuminate/support ~5.0 -> no matching package found.
    - laracasts/testdummy 1.2 requires illuminate/support ~5.0 -> no matching package found.
    - Installation request for laracasts/testdummy ~1.2 -> satisfiable by laracasts/testdummy[1.2, 1.3, 1.3.1, 1.3.2, 1.3.3].

[Proposal] Add attributes method to BuildableRepositoryInterface

With the current state of the Builder class. Assumptions are made that BuildableRepositoryInterface::build should return an instance of Illuminate\Database\Eloquent\Model and not mixed as is defined. The reason for this is that Builder::persist calls a method getAttributes on the returned entity.

I propose this should be abstracted away into the BuildableRepositoryInterface by means of an attributes method or something similar. This should allow for something else than Eloquent to be used.

Relationships using Factories

In the Builder.php class, in the persist function, there's the following:

    protected function persist($name, array $attributes = [])
    {
        $entity = $this->build($name, $attributes);
        $attributes = $this->database->getAttributes($entity);

        // We'll filter through all of the columns, and check
        // to see if there are any defined relationships. If there
        // are, then we'll need to create those records as well.
        foreach ($attributes as $columnName => $value)
        {
            if ($relationship =  $this->hasRelationshipAttribute($value))
            {
                $entity[$columnName] = $this->fetchRelationship($relationship);
            }
        }
        $this->database->save($entity);
        return $entity;
    }

Instead of $this->database->getAttributes($entity), shouldn't it be getting the key/values from the factory and not the attributes from the database? Then when it loops through those key/values, it's able to find the 'factory: ' relationships that are defined in our factories file?

Factory::create assign empty string instead of null

In a project I had a foreign key who should be null are a valid id, I notice TestDummy doesn't assign a valid null when creating but assign an empty string ("").

I reproduce this issues on a simple exemple:

Migration

Schema::create('posts', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('title')->nullable();
    $table->timestamps();
});

Model

class Post extends \Eloquent {
    protected $fillable = ['title'];
}

UnitTest

public function testBasicExample()
{
     $post = TestDummy::create("Post",['title'=>null]);
     $this->assertNull($post->title);
}

Result

1) ExampleTest::testBasicExample
Failed asserting that '' is null.

Overrides don't work with relations

So here is the issue. I have a user which has one role (role_id). When I create the user with TestDummy with overrides it gives an error while it creating the associated role!

This is my setup

// tests/factories/factories.php

$factory('App\User', [
    'name' => $faker->name,
    'email' => $faker->email,
    'password' => $faker->word,
    'role_id' => 'factory:Sebwite\Entry\Models\Role',
    'created_at' => $faker->date(),
    'updated_at' => $faker->date()
]);

$factory('Sebwite\Entry\Models\Role', [
    'name' => $faker->name,
    'display_name' => $faker->name,
    'description' => $faker->sentence(),
    'created_at' => $faker->date(),
    'updated_at' => $faker->date()
]);

Note that the Role model is from a package, but I think it shouldn't matter since it's namespaced correctly.

And now the test part

// tests/_support/FunctionalHelper

 public function signIn()
{
        $email = '[email protected]';
        $password = 'password';
        $this->haveAnAccount(compact('email', 'password'));

        $I = $this->getModule('Laravel5');

        $I->amOnPage('/login');
        $I->fillField('email', $email);
        $I->fillField('password', $password);
        $I->click('Login');
}

public function haveAnAccount($overrides = [])
{
        return TestDummy::create('App\User', $overrides);
}

This is the error

Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 table roles has no column named password (SQL: insert into "roles" ("name", "display_name", "description", "created_at", "updated_at", "email", "password") values (Vince Graham, Camila Mayert, Quis molestiae laboriosam id ea expedita., 2010-11-30 00:00:00, 1998-08-18 00:00:00, [email protected], password))

As you can see in the error it tries to insert the overrides for the User model in the Role model, while that shouldn't be happening!

If you need anything else please let me know!

Overriding relation attributes

At the moment to set overrides on a relationship object I need to initiate both manually...

$dummyBrand = TestDummy::create('Brand', [
    'slug' => 'the-brand-slug',
]);
TestDummy::create('Trip', [
    'slug'     => 'the-trip-slug',
    'brand_id' => $dummyBrand->id,
]);

In the example above.. I'd like to see a method of overriding Brand attributes via a Trip create()

TestDummy::create('Trip', [
    'slug'     => 'the-trip-slug',
    'brand_id' => [
        'slug' => 'the-brand-slug',
    ],
]);

I could probably implement this, but wanted to see if anyone else would benefit first!

One To One Relationships

The app I'm currently building has users able to link to another user as a one to one relationship. However, TestDummy doesn't particularly like that since it recursively creates more and more User objects and then blows up.

Example yaml file

User:
  email: $string@$string.com
  password: $string
  fiance_id:
      type: User

Error locating fixtures.yml file

I am having any issue where TestDummy cant locate the fixtures.yml file. I have placed it in numerous directories but nothing is working.

  • in 'tests' directory
  • in testssupport' directory
  • in same directory as the test I am running (using PHPUnit)

Any suggestions here?

Laracasts\TestDummy\TestDummyException: Could not locate the fixtures.yml file.

/Users/mikee/Documents/Projects/rangladex/vendor/laracasts/testdummy/src/Laracasts/TestDummy/FixturesFinder.php:45
/Users/mikee/Documents/Projects/rangladex/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php:89
/Users/mikee/Documents/Projects/rangladex/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php:34
/Users/mikee/Documents/Projects/rangladex/vendor/laracasts/testdummy/src/Laracasts/TestDummy/Factory.php:72
/Users/mikee/Documents/Projects/rangladex/app/tests/api/resourcetest.php:168

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.