GithubHelp home page GithubHelp logo

expecta's Introduction

Expecta Build Status Pod Version

A matcher framework for Objective-C and Cocoa.

FEATURES

The main advantage of using Expecta over other matcher frameworks is that you do not have to specify the data types. Also, the syntax of Expecta matchers is much more readable and does not suffer from parenthesitis.

expect(@"foo").to.equal(@"foo"); // `to` is a syntactic sugar and can be safely omitted.
expect(foo).notTo.equal(1);
expect([bar isBar]).to.equal(YES);
expect(baz).to.equal(3.14159);

Expecta is framework-agnostic: it works well with XCTest and XCTest-compatible test frameworks such as Specta, or Kiwi.

MATCHERS

expect(x).to.equal(y); compares objects or primitives x and y and passes if they are identical (==) or equivalent isEqual:).

expect(x).to.beIdenticalTo(y); compares objects x and y and passes if they are identical and have the same memory address.

expect(x).to.beNil(); passes if x is nil.

expect(x).to.beTruthy(); passes if x evaluates to true (non-zero).

expect(x).to.beFalsy(); passes if x evaluates to false (zero).

expect(x).to.contain(y); passes if an instance of NSArray or NSString x contains y.

expect(x).to.beSupersetOf(y); passes if an instance of NSArray, NSSet, NSDictionary or NSOrderedSet x contains all elements of y.

expect(x).to.haveCountOf(y); passes if an instance of NSArray, NSSet, NSDictionary or NSString x has a count or length of y.

expect(x).to.beEmpty(); passes if an instance of NSArray, NSSet, NSDictionary or NSString x has a count or length of .

expect(x).to.beInstanceOf([Foo class]); passes if x is an instance of a class Foo.

expect(x).to.beKindOf([Foo class]); passes if x is an instance of a class Foo or if x is an instance of any class that inherits from the class Foo.

expect([Foo class]).to.beSubclassOf([Bar class]); passes if the class Foo is a subclass of the class Bar or if it is identical to the class Bar. Use beKindOf() for class clusters.

expect(x).to.beLessThan(y); passes if x is less than y.

expect(x).to.beLessThanOrEqualTo(y); passes if x is less than or equal to y.

expect(x).to.beGreaterThan(y); passes if x is greater than y.

expect(x).to.beGreaterThanOrEqualTo(y); passes if x is greater than or equal to y.

expect(x).to.beInTheRangeOf(y,z); passes if x is in the range of y and z.

expect(x).to.beCloseTo(y); passes if x is close to y.

expect(x).to.beCloseToWithin(y, z); passes if x is close to y within z.

expect(^{ /* code */ }).to.raise(@"ExceptionName"); passes if a given block of code raises an exception named ExceptionName.

expect(^{ /* code */ }).to.raiseAny(); passes if a given block of code raises any exception.

expect(x).to.conformTo(y); passes if x conforms to the protocol y.

expect(x).to.respondTo(y); passes if x responds to the selector y.

expect(^{ /* code */ }).to.notify(@"NotificationName"); passes if a given block of code generates an NSNotification named NotificationName.

expect(^{ /* code */ }).to.notify(notification); passes if a given block of code generates an NSNotification equal to the passed notification.

expect(x).to.beginWith(y); passes if an instance of NSString, NSArray, or NSOrderedSet x begins with y. Also liased by startWith

expect(x).to.endWith(y); passes if an instance of NSString, NSArray, or NSOrderedSet x ends with y.

expect(x).to.match(y); passes if an instance of NSString x matches regular expression (given as NSString) y one or more times.

Inverting Matchers

Every matcher's criteria can be inverted by prepending .notTo or .toNot:

expect(x).notTo.equal(y); compares objects or primitives x and y and passes if they are not equivalent.

Asynchronous Testing

Every matcher can be made to perform asynchronous testing by prepending .will, .willNot or after(...):

expect(x).will.beNil(); passes if x becomes nil before the default timeout.

expect(x).willNot.beNil(); passes if x becomes non-nil before the default timeout.

expect(x).after(3).to.beNil(); passes if x becoms nil after 3.0 seconds.

expect(x).after(2.5).notTo.equal(42); passes if x doesn't equal 42 after 2.5 seconds.

The default timeout is 1.0 second and is used for all matchers if not otherwise specified. This setting can be changed by calling [Expecta setAsynchronousTestTimeout:x], where x is the desired timeout in seconds.

describe(@"Foo", ^{
  beforeAll(^{
    // All asynchronous matching using `will` and `willNot`
    // will have a timeout of 2.0 seconds
    [Expecta setAsynchronousTestTimeout:2];
  });

  it(@"will not be nil", ^{
    // Test case where default timeout is used
    expect(foo).willNot.beNil();
  });

  it(@"should equal 42 after 3 seconds", ^{
    // Signle case where timeout differs from the default
    expect(foo).after(3).to.equal(42);
  });
});

Forced Failing

You can fail a test by using the failure attribute. This can be used to test branching.

failure(@"This should not happen"); outright fails a test.

WRITING NEW MATCHERS

Writing a new matcher is easy with special macros provided by Expecta. Take a look at how .beKindOf() matcher is defined:

EXPMatchers+beKindOf.h

#import "Expecta.h"

EXPMatcherInterface(beKindOf, (Class expected));
// 1st argument is the name of the matcher function
// 2nd argument is the list of arguments that may be passed in the function
// call.
// Multiple arguments are fine. (e.g. (int foo, float bar))

#define beAKindOf beKindOf

EXPMatchers+beKindOf.m

#import "EXPMatchers+beKindOf.h"

EXPMatcherImplementationBegin(beKindOf, (Class expected)) {
  BOOL actualIsNil = (actual == nil);
  BOOL expectedIsNil = (expected == nil);

  prerequisite(^BOOL {
    return !(actualIsNil || expectedIsNil);
    // Return `NO` if matcher should fail whether or not the result is inverted
    // using `.Not`.
  });

  match(^BOOL {
    return [actual isKindOfClass:expected];
    // Return `YES` if the matcher should pass, `NO` if it should not.
    // The actual value/object is passed as `actual`.
    // Please note that primitive values will be wrapped in NSNumber/NSValue.
  });

  failureMessageForTo(^NSString * {
    if (actualIsNil)
      return @"the actual value is nil/null";
    if (expectedIsNil)
      return @"the expected value is nil/null";
    return [NSString
        stringWithFormat:@"expected: a kind of %@, "
                          "got: an instance of %@, which is not a kind of %@",
                         [expected class], [actual class], [expected class]];
    // Return the message to be displayed when the match function returns `YES`.
  });

  failureMessageForNotTo(^NSString * {
    if (actualIsNil)
      return @"the actual value is nil/null";
    if (expectedIsNil)
      return @"the expected value is nil/null";
    return [NSString
        stringWithFormat:@"expected: not a kind of %@, "
                          "got: an instance of %@, which is a kind of %@",
                         [expected class], [actual class], [expected class]];
    // Return the message to be displayed when the match function returns `NO`.
  });
}
EXPMatcherImplementationEnd

DYNAMIC PREDICATE MATCHERS

It is possible to add predicate matchers by simply defining the matcher interface, with the matcher implementation being handled at runtime by delegating to the predicate method on your object.

For instance, if you have the following class:

@interface LightSwitch : NSObject
@property (nonatomic, assign, getter=isTurnedOn) BOOL turnedOn;
@end

@implementation LightSwitch
@synthesize turnedOn;
@end

The normal way to write an assertion that the switch is turned on would be:

expect([lightSwitch isTurnedOn]).to.beTruthy();

However, if we define a custom predicate matcher:

EXPMatcherInterface(isTurnedOn, (void));

(Note: we haven't defined the matcher implementation, just it's interface)

You can now write your assertion as follows:

expect(lightSwitch).isTurnedOn();

INSTALLATION

You can setup Expecta using CocoaPods, Carthage or completely manually.

CocoaPods

  1. Add Expecta to your project's Podfile:
target :MyApp do
# your app dependencies

  target :MyAppTests do
    inherit! search_paths

    pod 'Expecta', '~> 1.0'
  end
end

Carthage

  1. Add Expecta to your project's Cartfile.private:

    github "specta/expecta" "master"
  2. Run carthage update in your project directory.

  3. Drag the appropriate Expecta.framework for your platform (located in Carthage/Build/) into your application’s Xcode project, and add it to your test target(s).

  4. Run pod update or pod install in your project directory.

Setting Up Manually

  1. Clone Expecta from Github.

  2. Run rake in your project directory to build the frameworks and libraries.

  3. Add a Cocoa or Cocoa Touch Unit Testing Bundle target to your Xcode project if you don't already have one.

  4. For OS X projects, copy and add Expecta.framework in the Products/osx folder to your project's test target.

    For iOS projects, copy and add Expecta.framework in the Products/ios folder to your project's test target.

    You can also use libExpecta.a if you prefer to link Expecta as a static library — iOS 7.x and below require this.

  5. Add -ObjC and -all_load to the Other Linker Flags build setting for the test target in your Xcode project.

  6. You can now use Expecta in your test classes by adding the following import:

    @import Expecta; // If you're using Expecta.framework
    
    // OR
    
    #import <Expecta/Expecta.h> // If you're using the static library, or the framework

STATUS

Expecta, and Specta are considered done projects, there are no plans for active development on the project at the moment aside from ensuring future Xcode compatability. Therefore it is a stable dependency, but will not be moving into the Swift world. If you are looking for that, we recommend you consider Quick and Nimble.

Contribution Guidelines

  • Please use only spaces and indent 2 spaces at a time.
  • Please prefix instance variable names with a single underscore (_).
  • Please prefix custom classes and functions defined in the global scope with EXP.

License

Copyright (c) 2012-2016 Specta Team. This software is licensed under the MIT License.

expecta's People

Contributors

andrewsardone avatar ashfurrow avatar blakewatters avatar chrismaddern avatar chrispix avatar dchohfi avatar erichoracek avatar gfontenot avatar iabudiab avatar iosdev-republicofapps avatar jmoody avatar jspahrsummers avatar kseebaldt avatar lukeredpath avatar michaelengland avatar nickhutchinson avatar nsforge avatar ollieatkinson avatar orta avatar petejkim avatar rlisle avatar robb avatar segiddins avatar spekke avatar sspitzer avatar statusreport avatar tibr avatar tonyarnold avatar vmalyi avatar zachwaugh 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  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

expecta's Issues

0.2.4

I think this is a good time to make a 0.2.4 since people seem to be waiting for a release containing #63 and #55 (See #76 and #77).

If there's anything that should go into 0.2.4, please let me know and I'll look into it over the weekend. Otherwise and if @petejkim is cool with it, I'd tag the current master (currently ef0601d)

Method Invocation With Indirect Pointer Inside expect() Triggers compiler error

NSString *input = @"http://google.com/";
    NSURL *output;
    NSError *error;
expect([transformer transformValue:input toValue:&output error:&error]).to.beTruthy();

Yields the compiler error Sending 'NSURL *const __strong *' to parameter of type '__autoreleasing id *' changes retain/release properties of pointer. Likely related to http://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4.

Asserting NSNumbers, expected: 10.2, got: 10.2 (FAILURE)

I have the following Calculator class:

...
-(NSNumber *)multiply:(NSNumber *)x with:(NSNumber *)y{
    NSNumber *sum = [NSNumber numberWithFloat:([x floatValue] * [y floatValue])];
    return sum;
}

when I test any float operands, for example in CalculatorTest:

describe(@"When operands are Floats", ^{
...
  it(@"multiply", ^{
      expect([calculator multiply:@3.4 with:@3]).to.equal(@10.2);
    });
});

I get the following output:

- When operands are Floats multiply (FAILURE)
    /Users/victor/Github/Calculator/CalculatorTests/CalculatorTests.m:78

    expected: 10.2, got: 10.2

I don't know if I did something wrong or this is a bug.
Here is the link to the project for any other details:
GitHub - Calculator

Latest Pod Does not include "notify"

It seems that the latest cocoapod does not include the notify matcher. Is this something I am missing, or can you please push out your latest to cocoapods?

Love the syntax! Thanks in advance.

expect(x).toBeInstanceOf([Foo class]) - seems to be broken

To reproduce:

Song* song = [[Song alloc] initWithTitle: @"Rehab" andArtist: @"Amy Winehouse"
andReleaseDate: [[NSDate alloc] initWithString: @"2001-03-24 00:00:00 +0"]];

expect(song).toBeInstanceOf([Song class]);

Outcome:

Fails: Expected an instance of Song, got an instance of NSConcreteValue

Using OCHamcrest:

assertThat(song, instanceOf([Song class])); - works.

Asserting that all objects in an NSArray are of a specific class

Is there an existing way to check that all objects in an NSArray are of a specific type?

If not, would you be open to a pull request with an interface as follows?

Syntax:

NSArray *x; // x can be NSArray, NSSet (NSDictionary? Checking only values?)
expect(x).to.containOnlyInstancesOf([XXClass class]);
expect(x).to.containOnlyKindsOf([XXClass class]);
expect(x).to.containOnlySubclassesOf([XXClass class]);

Regards,
Jon

Specta

What's the reasoning behind not using specta for testing expecta? Is it circular submodules?

Tests succeed with Expecta, but Xcode reports Test Failed.

As you can see from the screenshot each and every one of the tests passed

17 tests; 0 skipped; 0 failures; 0 exceptions; 0 pending

However the error I am seeing is in the top right hand side of the screenshot - Test Failed is reported by Xcode.

Is this a setting I have got incorrect or is it an issue with Expecta?

screen shot 2014-02-26 at 22 49 22

to.equal() does not work for NS_OPTIONS

Given the expect, where button is an instance of UIButton

expect(button.state).after(2).to.equal(UIControlStateDisabled);

It will pass for any button.state.

button.state is defined with

typedef NS_OPTIONS(NSUInteger, UIControlState) {
    UIControlStateNormal       = 0,
    UIControlStateHighlighted  = 1 << 0,                  // used when UIControl isHighlighted is set
    UIControlStateDisabled     = 1 << 1,
    UIControlStateSelected     = 1 << 2,                  // flag usable by app (see below)
    UIControlStateApplication  = 0x00FF0000,              // additional flags available for application use
    UIControlStateReserved     = 0xFF000000               // flags reserved for internal framework use
};

The haveCountOf matcher should work with more collection classes

Currently, the haveCountOf matcher only works with instances of NSString, NSArray, NSSet or NSDictionary.

It would be nice if it also worked with the rarer collection classes such as NSPointerArray or NSOrderedSet.

I see two ways to achieve this: either it inspects the given instance if it responds to count and returns an NSUInteger or we just add the missing classes to the list. (NSString remains a special case either way).

I've found the following classes to implement count:

  • NSArray
  • NSDictionary
  • NSHashTable
  • NSIndexSet
  • NSMapTable
  • NSMetadataQueryAttributeValueTuple (This one we could skip)
  • NSOrderedSet
  • NSPointerArray
  • NSSet

Let me know which approach you'd prefer and I'm happy to implement it. I personally lean towards probing for count as it would also work with custom collection classes that follow the convention.

new compiler issues w/ XCode6 beta5

Having just updated to beta5, I'm seeing compiler errors in my spec where I wasn't before.

This is:
Using Specta (0.2.1)
Using Expecta (0.3.1)

screen shot 2014-08-05 at 9 45 17 am

thoughts?

Alternative Naming

I really love Expecta. But I'd like to offer what I think is a more natural naming scheme. By natural I mean that I would prefer if it read more like a sentence. Do you like it?

expect(object).beTruthy();
expect(object).to.beTruthy(); // to = no-op
expect(object).toNot.beTruthy(); // noNot = Not
expect(object).will.beTruthy(); // will = isGoing
expect(object).willNot.beTruthy(); // willNot = isNotGoing

// OR ALTERNATIVE CEDAR STYLE

expect(object).be_truthy();
expect(object).to.be_truthy();
expect(object).to_not.be_truthy();
expect(object).will.be_truthy();
expect(object).will_not.be_truthy();

Support OCMock expectations

For simple mocks

[[mock expect] someMethod:someArgument]

we would like to write

expect(original class).to.receive("someMethod").with(someArgument)

And more crazier :) Given something like this:

@interface AuthProviders : NSObject
+ (void)getTokenForFacebook:(void (^)(NSString *token, NSString *email, NSString *name))complete failure:(void(^)(NSError *error))failure;
@end

we stub it with OCMock

id authProvider = [OCMockObject mockForClass:[AuthProvider class]];
[[[authProvider stub] andDo:^(NSInvocation *invocation) {
   void(^successBlock)(NSString *token, NSString *email, NSString *name);
   [invocation getArgument:&successBlock atIndex:2];
   successBlock(@"facebook token", @"[email protected]", "Foo");
}] getTokenForFacebook:OCMOCK_ANY failure:OCMOCK_ANY];

A more sane person would like to write:

expect(AuthProviders).to.receive("getTokenForFacebook").and.do(arguments) ^{ ... }

or something along those lines ...

probably belongs in a separate expecta library ala https://github.com/dblock/ios-snapshot-test-case-expecta

Missing file

Hi Pete,

Looks like the Expecta-iOS target is missing a copy file step:

EXPMatchers+toBeInTheRangeOf.h

. . . does not appear in the build/Release-iPhoneOS directory.

Cheers,

Jasper

contains no longer works when checking if an NSArray of NSDictionaries contains an NSDictionary

The following code doesn't appear to work as of 93cfdb1:

NSDictionary *myDictionary = @{@"aKey" : @YES};
NSArray *myArray = @[myDictionary];

expect(myArray).to.contain(myDictionary);

It seems that the prerequisite code in the contains matcher is causing it to fail:

  prerequisite(^BOOL{
    return actualIsCompatible && !expectedIsNil &&
      bothOrNeitherDictionaries;
  });

We should be able to check if an array contains a dictionary as an item, shouldn't we?

Method of wrapping a temporary increase to the async spec timeout

Currently, with some of my tests I temporarily increase the asynchronousTestTimeout value, and reset it again to the default value at the end:

it(@"test test test", ^{
    NSTimeInterval asynchronousTestTimeout = [Expecta asynchronousTestTimeout];
    [Expecta setAsynchronousTestTimeout:30.f];

    …

    [Expecta setAsynchronousTestTimeout:asynchronousTestTimeout];
});

It would be nice to have a simple method to specify that either:

  1. Changes to the asynchronousTestTimeout value only affect the current context; or
  2. Allow specifying a timeout value for a context/it/block;

Async tests (wait) sometimes fail

I've got a test set up to wait for cache to be filled based on requests being sent (mocked via OHHTTPStubs).

- (void)test_fetchAdsIfNeeded
{
    [self mockResponseWithBlock:^OHHTTPStubsResponse *{
        return [self uniqueAdResponse];
    }];

    AdCache *cache = [AdCache currentValue];
    expect(cache.ads).to.haveCountOf(0);
    [cache fetchAdsIfNeeded];
    expect(cache.ads).will.haveCountOf(10);

    [OHHTTPStubs removeLastRequestHandler];
}

Sometimes this test will fail. It's not deterministic. My suspicion is that it is related to runloop event processing.

Now I'm far from an expert on this but I've compared applyMatcher: to my own async test extension which is based on GHUnit [1] and noticed that there's additional runloop processing going on in GHUnit.

I'll submit a pull request for this, which in my testing fixed the issue (but as non-deterministic issues go, this might not be the end-all fix).

[1] http://feinstruktur.com/blog/2012/8/12/unit-testing-asynchronous-code.html

to.beNil and notTo.beNil not working in XCode 5

Unless I've got something wrong, I'm sure nil checks are not working.

I've got XCode5, running in an iOS7 project.

For example, trying running this simple test method inside a XCTestCase subclass.

- (void)testExpectaNullTest
{
    id nilThing = nil;
    id nonNilThing = @[@1, @2];

    expect(nilThing).to.beNil;
    expect(nilThing).notTo.beNil;
    expect(nonNilThing).to.beNil;
    expect(nonNilThing).notTo.beNil;

}

That test should fail (because two of the expectations are false).
Yet XCode5 is reporting that they pass.

unable to do expect().contain with NSArray literals

If I do:

expect(@[ @5, @10 ]).contain(5);

It won't compile. I'll get:

Too many arguments provided to function-like macro invocation

Note that this works:

expect(@[ @5 ]).contain(5);

So it's the comma, which reminds me of "Make usage of NSArray literals a little bit simpler in equal()". issue #59

The fix is similar, here comes a pull request.

problem with will.beLessThan

Came across this:

Given an NSArray *types where types has 12 elements and types is set in a completionHandler the following test passes:

expect([types count]).will.beLessThan(1);

This test correctly fails:

expect([types count]).willNot.beLessThan(13);

Compatibility with Cedar

Hi!

I'm using Cocoa Pods to resolve dependencies. I also want to replace Cedar matchers with Expecta matchers. However it does not seem to work, or i'm probably doing something wrong.

Here's are my imports:

#define CEDAR_MATCHERS_COMPATIBILITY_MODE
#import <Cedar-iOS/SpecHelper.h>
#define EXP_SHORTHAND
#import <Expecta/Expecta.h>

When i try to use Expecta matchers, for example like this:

expect(@YES).to.beTruthy();

This gives me a compile error

No matching function for call to '_EXPObjectify'

`beNil`, `beTruthy` and `beFalsy` matchers will always pass under any condition

The test case below will pass without any error:

#import <XCTest/XCTest.h>

#define EXP_SHORTHAND
#import <Expecta/Expecta.h>

@interface ExpectaMatcherBugTests : XCTestCase

@end

@implementation ExpectaMatcherBugTests

- (void)setUp
{
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown
{
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample
{
    expect(@"").to.beNil;
    expect(nil).notTo.beNil;
    expect(NO).to.beTruthy;
    expect(YES).to.beFalsy;
}

@end

Example project: http://d.pr/f/zxpx/2NnFPK01

Matcher: haveLayoutConstraint

I'm trying to test that NSLayoutConstraints that have been added programmatically are being set.
I've created the following custom matcher:

#import "EXPMatchers+hasLayoutConstraint.h"

EXPMatcherImplementationBegin(hasLayoutConstraint, (NSLayoutConstraint *expected)) {

  match(^BOOL {

    for (NSLayoutConstraint *item in actual)
    {
      if (item.firstItem == expected.firstItem &&
          item.firstAttribute == expected.firstAttribute &&
          item.relation == expected.relation &&
          item.secondItem == expected.secondItem &&
          item.secondAttribute == expected.secondAttribute &&
          item.multiplier == expected.multiplier &&
          item.constant == expected.constant) {
        return YES;
      }
    }

    return NO;
  });

  failureMessageForTo(^NSString * {
    return @"The layout constraint is not found;";
  });

  failureMessageForNotTo(^NSString * {
    return @"The unexpected layout constraint was found in the given array.";
  });
}
EXPMatcherImplementationEnd

If this would be useful to anyone else, I'd love to see it implemented.

XCode 5.NEXT / Linker Errors

Hello. I'm not sure this is the best place to raise this issue. I've installed Expecta through Cocoapods — and when I run a unit test containing expecta statements, I get several linker errors. I can whack-a-mole quiet them by manually adding source code, but that doesn't seem right. About 1/2 a day into trying to figure this out, so I thought I'd ask rather than pull my own teeth.

I'm on XCode Version 5.1 (5B90f)

Any ideas? Also happy to take this on a different wire: julian at nearfuturelaboratory dot com

My Podfile contains:

platform :ios, '7.0'
#pod 'AFNetworking', '~> 1.3.3'
pod 'SSToolkit'
pod 'ConciseKit'
pod 'SBJson'
pod 'RestKit'
pod 'SSKeychain'
pod 'SAMCache'
pod 'iCarousel'
pod 'GMGridView'
pod 'NSLogger'
pod 'MGBoxKit'
target :humansTests, :exclusive => true do
        pod 'OCHamcrest', '~> 3.0.1'
         pod 'OCMockito', '~> 1.0'
  pod 'Specta',      '~> 0.2.1'
   pod 'Expecta',     '~> 0.2.3'   # expecta matchers
   pod 'OCMock',      '~> 2.2.1'   # OCMock
   pod 'LRMocky',     '~> 0.9.1'   # LRMocky
end
post_install do |installer_representation|
    installer_representation.project.targets.each do |target|
        if target.name == 'Pods-AFNetworking'
            target.build_configurations.each do |config|
                config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
                config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << '_AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_=1'
            end
        end
    end
end

The linker errors look like this, for two statements:

- (void)test_foogetStatusCountForHuman
{
    [Expecta setAsynchronousTestTimeout:10];
    expect(@"foo").to.equal(@"foo");
}

Undefined symbols for architecture i386:
  "_OBJC_CLASS_$_Expecta", referenced from:
      objc-class-ref in HuUserHandlerTest.o
  "__EXPObjectify", referenced from:
      -[HuUserHandlerTest test_foogetStatusCountForHuman] in HuUserHandlerTest.o
      ___51-[HuUserHandlerTest test_foogetStatusCountForHuman]_block_invoke in HuUserHandlerTest.o
  "__EXP_expect", referenced from:
      -[HuUserHandlerTest test_foogetStatusCountForHuman] in HuUserHandlerTest.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

'beSupersetOf' fails to compare mutable collection with immutable one

Example:

    NSString *string = @"Test";
    NSArray *arrA = @[string];
    NSArray *arrB = @[string];

    expect(arrA).to.beSupersetOf(arrB);

    NSMutableArray *arrAm = [arrB mutableCopy];
    expect(arrAm).to.beSupersetOf(arrB);   //  this fails

Result is an error: (Test) does not match the class of (Test) , which is obvious.

Looking inside debugger:

(lldb) po actual
<__NSArrayM 0xe187910>(
Test
)
(lldb) po subset
<__NSArrayI 0xe17e820>(
Test
)

Is this me, that is using this in an incorrect way, or actually a bug?

Also, IMHO, error is not really meaningful, as for big collections it prints load of useless info (collection contents) when the point of this message is about subset/actual class types.

Thanks!

Forgetting brackets silently passes

This is maybe not worth worrying about but worth mentioning:

If you forget to put brackets at the end of a statement, like so:

expect([hosts count] > 7).to.beTruthy;

. . then it will just pass. .

(not sure how it works and/or how you'd fix it)

beNil, beTruthy, and beFalsy should not accept incorrect syntax.

It's really easy to mistakenly use the incorrect syntax with beNil, beTruthy, and beFalsy and end up with conditions that always pass, e.g.

expect(YES).to.beNil;
expect(NO).to.beTruthy;
expect(YES).to.beFalsy;

Some kind of warning or syntax error would be really helpful.

will/willNot not working as expected

I'm currently porting the MagicalRecord tests across to Specta/Expecta, and I've hit a problem that I'm having trouble resolving. Given the following test:

describe(@"saveInBackgroundWithBlock:completion:", ^{
    it(@"should call completion block", ^{
        __block BOOL completionBlockCalled = NO;

        [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
            [SingleEntityWithNoRelationships MR_createInContext:localContext];
        } completion:^{
            completionBlockCalled = YES;
        }];

        expect(completionBlockCalled).will.beTruthy;
    });

    it(@"should save", ^{
        __block NSManagedObjectID *objectId;
        __block NSManagedObject *fetchedObject;

        [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
            NSManagedObject *inserted = [SingleEntityWithNoRelationships MR_createInContext:localContext];
            [localContext obtainPermanentIDsForObjects:@[inserted] error:nil];
            objectId = [inserted objectID];
        } completion:^{
            fetchedObject = [[NSManagedObjectContext MR_rootSavingContext] objectRegisteredForID:objectId];
        }];

        expect(objectId).willNot.beNil;
        expect(fetchedObject).willNot.beNil;
        expect([fetchedObject hasChanges]).will.beFalsy;
    });
});

I would expect that the expect(…).will.… calls would cause execution of this test to pause until the timeout passes. Sadly, the test returns almost immediately, and without waiting.

Am I doing something wrong here? It's the first time I've used the async additions to Expecta.

Expecta should be packaged as a framework

Consider packaging Expecta as a framework.

To reproduce:

  1. Try to incorporate Expecta into a project.

Expected Outcome:

  1. Fetch a framework dependency - using Rake/Ivy/manually/whatever.
  2. Drag it into the project workspace.

Actual Outcome:

Need to add headers and lib as separate steps.

Defined aliases conflict with existing method names

Aliases of the kind #define startWith beginWith defined in EXPMatchers+beginWith.h cause issues when they conflict with existing method names defined elsewhere.

For example:

#import <Expecta.h>

...

// Then, somewhere in the test
[someObject startWith:@1];

Results in [someObject startWith:@1] being compiled as [someObject beginWith:@1], which causes inexplicable looking build errors:
screen shot 2014-03-26 at 12 17 28

A real-world example of this is ReactiveCocoa's [RACStream startWith:], which causes a runtime exception: -[RACDynamicSignal beginWith:]: unrecognized selector sent to instance

It's not uncommon for these aliases to have real-world usage elsewhere - they need an alternative to #defineing to avoid the find and replace style behaviour that causes.

Release Expecta 0.3.0

I've just pushed all of the necessary changes to support Xcode/Apple LLVM 5.1 into develop, and updated the documentation and the podspec. @specta/members, would you mind giving this a quick run through and making sure I've not missed anything?

super matchers?

I'm curious if you've thought about introducing super matchers (sort of like in rails where you can include spec helpers like behaves_like_authenticating_controller)

I'm thinking it would be nice to have sane checks for NSCopying and NSCoding etc.

If you're interested I'll write up a first pass

Noob Question: Compiler Warnings -> "Implicit declaration of function..."

I'm screwing up somewhere under IOS 7, xCode Version 5.0 (5A1412) and Mavericks and am getting the following warning:

Implicit declaration of function ‘expect’ is invalid in C99
  1. Installed via Pods, ala'

target :MyAppNameTests do
pod 'Expecta', '~> 0.2.3' # expecta matchers
end
2. In the testClass harness:

// Mocking and Such

define EXP_Shorthand

import "Expecta.h"

  1. And in my just getting started test
  • (void) testExpectaWorking{
    expect(@"foo").to.equal(@"foo"); // to is a syntatic sugar and can be safely omitted.

}

Any help greatly appreciated.

matcher to check if array contains an object matching a block

I recently wrote some code like this:

expect([array[0] someProperty]).to.equal(@"a");
expect([array[0] otherProperty]).to.equal(@1);

expect([array[1] someProperty]).to.equal(@"b");
expect([array[1] otherProperty]).to.equal(@2);

Now, I really don't care for the order of the elements of array, but couldn't find a better expecta-ish way to confirm both objects are present in the array.

I think for things like this, it would be nice to have a matcher that would make the code above a bit like this:

expect(array).to.containElementPassing(^(id o){
    expect([o someProperty]).to.equal(@"a");
    expect([o otherProperty]).to.equal(@1);
});

expect(array).to.containElementPassing(^(id o){
    expect([o someProperty]).to.equal(@"b");
    expect([o otherProperty]).to.equal(@2);
});

I'm not sure it could be implemented like this, and would also be happy if the block just returns a BOOL and that is what is used.

If something like this does make it into Expecta, it would also be nice to have something like containOnlyElementsPassing(). (Basically rubys all? and any?)

Property 'beSupersetOf' not found on object of type EXPExpect *

I'm trying to do the following:

expect(items).to.beSupersetOf(@[@"hello", @"world"]);

and I get the error Property 'beSupersetOf' not found on object of type EXPExpect *

I'm using 0.2.3 via CocoaPods and I don't see the EXPMatchers+beSupersetOf files under Pods > Expecta.

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.