kiwi-bdd / kiwi Goto Github PK
View Code? Open in Web Editor NEWSimple BDD for iOS
License: BSD 3-Clause "New" or "Revised" License
Simple BDD for iOS
License: BSD 3-Clause "New" or "Revised" License
I'd like to be able to stub methods in the AppDelegate.
I'm attempting to stub a method in the AppDelegate like this:
[FooAppDelegate stub:@selector(bar) andReturn:self.bar];
And it's failing with the following message:
"cannot stub -bar because no such method exists"
I've triple-checked, and -bar
most definitely does exist.
According to the documentation beforeAll is "is run once before all the inner contexts and it blocks of the context it is in". However, it appears to be running all beforeAll blocks before every "it" block no matter which context it is in. The following code produces the output shown.
SPEC_BEGIN(TestSpec)
describe(@"Testing", ^{
beforeAll(^{
NSLog(@"Running before all 1");
});
it(@"example 1", ^{
NSLog(@"Running example 1");
});
context(@"Context 1", ^{
beforeAll(^{
NSLog(@"Running before all 1.1");
});
it(@"example 2", ^{
NSLog(@"Running example 1.1");
});
context(@"Context 1.1", ^{
beforeAll(^{
NSLog(@"Running before all 1.1.1");
});
it(@"example 3", ^{
NSLog(@"Running example 1.1.1");
});
context(@"Context 1.1.1", ^{
it(@"example 4", ^{
NSLog(@"Running example 1.1.1.1");
});
});
});
});
context(@"Context 2", ^{
beforeAll(^{
NSLog(@"Running before all 2");
});
it(@"example 2", ^{
NSLog(@"Running example 2");
});
context(@"Context 2.1", ^{
beforeAll(^{
NSLog(@"Running before all 2.1");
});
it(@"example 3", ^{
NSLog(@"Running example 2.1.1");
});
context(@"Context 2.1.1", ^{
it(@"example 4", ^{
NSLog(@"Running example 2.1.1.1");
});
});
});
});
});
SPEC_END
Test Suite 'TestSpec' started at 2011-10-15 04:56:19 +0000
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.748 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.749 MyTestApp[42950:207] Running example 1
2011-10-14 21:56:19.749 MyTestApp[42950:207] + 'Testing example 1' [PASSED]
2011-10-14 21:56:19.750 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.758 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.759 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.760 MyTestApp[42950:207] Running before all 2.1
Test Case '-[TestSpec example]' passed (0.012 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.761 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.761 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.762 MyTestApp[42950:207] Running example 1.1
2011-10-14 21:56:19.762 MyTestApp[42950:207] + 'Testing In Context 1 example 2' [PASSED]
2011-10-14 21:56:19.763 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.763 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.764 MyTestApp[42950:207] Running before all 2.1
Test Case '-[TestSpec example]' passed (0.004 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.765 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.796 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.797 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.798 MyTestApp[42950:207] Running example 1.1.1
2011-10-14 21:56:19.799 MyTestApp[42950:207] + 'Testing In Context 1 Context 1.1 example 3' [PASSED]
2011-10-14 21:56:19.800 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.800 MyTestApp[42950:207] Running before all 2.1
Test Case '-[TestSpec example]' passed (0.036 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.801 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.802 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.803 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.803 MyTestApp[42950:207] Running example 1.1.1.1
2011-10-14 21:56:19.804 MyTestApp[42950:207] + 'Testing In Context 1 Context 1.1 Context 1.1.1 example 4' [PASSED]
2011-10-14 21:56:19.805 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.818 MyTestApp[42950:207] Running before all 2.1
Test Case '-[TestSpec example]' passed (0.018 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.819 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.820 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.821 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.822 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.822 MyTestApp[42950:207] Running example 2
2011-10-14 21:56:19.823 MyTestApp[42950:207] + 'Testing In Context 2 example 2' [PASSED]
2011-10-14 21:56:19.824 MyTestApp[42950:207] Running before all 2.1
Test Case '-[TestSpec example]' passed (0.005 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.824 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.825 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.826 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.826 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.827 MyTestApp[42950:207] Running before all 2.1
2011-10-14 21:56:19.827 MyTestApp[42950:207] Running example 2.1.1
2011-10-14 21:56:19.828 MyTestApp[42950:207] + 'Testing In Context 2 Context 2.1 example 3' [PASSED]
Test Case '-[TestSpec example]' passed (0.005 seconds).
Test Case '-[TestSpec example]' started.
2011-10-14 21:56:19.829 MyTestApp[42950:207] Running before all 1
2011-10-14 21:56:19.830 MyTestApp[42950:207] Running before all 1.1
2011-10-14 21:56:19.830 MyTestApp[42950:207] Running before all 1.1.1
2011-10-14 21:56:19.831 MyTestApp[42950:207] Running before all 2
2011-10-14 21:56:19.831 MyTestApp[42950:207] Running before all 2.1
2011-10-14 21:56:19.832 MyTestApp[42950:207] Running example 2.1.1.1
2011-10-14 21:56:19.832 MyTestApp[42950:207] + 'Testing In Context 2 Context 2.1 Context 2.1.1 example 4' [PASSED]
Test Case '-[TestSpec example]' passed (0.005 seconds).
Test Suite 'TestSpec' finished at 2011-10-15 04:56:19 +0000.
Executed 7 tests, with 0 failures (0 unexpected) in 0.086 (0.086) seconds
Is this possible to only run specs in a certain file?
Luke, do you have a preference for where the website is located? I would like feedback on whether to move it to github, or simply to get rid of the page altogether and use the wiki on github for all documentation. This would also make it easier for everyone involved to edit it, including updating it with contributors and status. If you would prefer, I can look into setting up access for you on dream host where the actual site is located too. (http://www.kiwi-lib.info)
Let me know what you think, and anyone else can chime in as well.
Do you think it makes sense to drop support for Xc3.x? Seems like most people have moved on to 4, which has test runners set up differently, so the reference to the 'on device' testing in the project and KiwiDriver project don't make sense anymore.
xit(@"does something", ^{});
might be nice to make it equivalent to:
pending(@"does something", ^{});
http://relishapp.com/rspec/rspec-core/v/2-6/dir/pending/pending-examples#4
It seems that Kiwi, like GHUnit, has support for async testing.
It'd be nice to include an example async test case on the documentation on the website:
GHUnit does this:
http://gabriel.github.com/gh-unit/_examples.html#ExampleAsyncTestCase
I think this is important because many users ask for async testing.
Have you seen Artifice? It's so cool.
I think we could make something similar using objective-c categories. Although, I'm not sure. It may take more trickery and changing some of the implementation details.
Anyway, how should I mock network stuff for NSURLConnection
. Also, I'm working on a project that uses ASIHTTP
. Although I prefer NSURLConnection
, I'd still like to know how to mock ASIHTTP
responses as well.
In some cases, it makes sense for Kiwi to handle a nil subject. Here's an example:
[[myBar.foo shouldNot] equal:baz];
If foo
is nil and baz
is not nil, this should pass. When I ran this and foo
was nil, I received the error message: "expected subject not to be nil."
When I run my spec for the method that calls the dispatch_async block, any expectation I have set on the code inside that dispatch_async block is never met. This makes sense, since it is spun off on to a background thread, but I am wondering how to spec code like this?
something like:
-(void)foo
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSInteger result = [self.object bigLongTask];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate messenger:self completedWithResult:result];
});
});
}
// spec
describe(@"-foo", ^{
it(@"informs the delegate when complete", ^{
id delegateMock = [KWMock mockForProtocol:@protocol(MessengerDelegate)];
[[messenger should] receive:@selector(delegate) andReturn:delegateMock];
[[delegateMock should] receive:@selector(messenger:completedWithResult:)];
[messenger foo];
});
});
This is a simple example, but I still want to have test coverage. Any ideas?
When I comment out the first describe
block, I don't get any errors. Weird.
Errors on lines 33 & 34, 65 & 68, respectively:
file://localhost/Users/matt/Projects/My/MySDK/MySpecs/MyClientSpecs.m: error: runSpec (MyClientSpecs) failed: "MyClient -viewControllerWithTransaction:forceWeb: sets the returned MyViewController's transactionURL" FAILED, expected subject to be identical to https://my.com/ (0x867d080), got http://my.com/touch/signup_to_pay/?app_id=your_app_id&txn=pay&amount=3.45¬e=hello%20world&recipients=kortina,mattdipasquale (0x867d6e0)
file://localhost/Users/matt/Projects/My/MySDK/MySpecs/MyClientSpecs.m: error: runSpec (MyClientSpecs) failed: "MyClient -viewControllerWithTransaction:forceWeb: sets the returned MyViewController's transactionURL" FAILED, expected subject to receive -safariURLWithPath: exactly 1 time, but received it 0 times
file://localhost/Users/matt/Projects/My/MySDK/MySpecs/MyClientSpecs.m: error: runSpec (MyClientSpecs) failed: "MyClient -viewControllerWithTransaction:forceWeb: sets the returned MyViewController's transactionURL" FAILED, expected subject to be identical to https://my.com/ (0x867d080), got http://my.com/touch/signup_to_pay/?app_id=your_app_id&txn=pay&amount=3.45¬e=hello%20world&recipients=kortina,mattdipasquale (0x867d6e0)
file://localhost/Users/matt/Projects/My/MySDK/MySpecs/MyClientSpecs.m: error: runSpec (MyClientSpecs) failed: "MyClient -viewControllerWithTransaction:forceWeb: sets the returned MyViewController's transactionURL" FAILED, expected subject to receive -safariURLWithPath: exactly 1 time, but received it 0 times
__block MyClient *client;
__block NSString *URLPath;
__block MyTransaction *transaction;
beforeEach(^{
client = [[MyClient alloc] initWithAppId:@"your_app_id" secret:@"your_app_secret"];
URLPath = @"/?key=value";
transaction = [[MyTransaction alloc] init];
transaction.type = MyTransactionTypePay;
transaction.amount = 3.45f;
transaction.note = @"hello world";
transaction.recipients = [NSArray arrayWithObjects:@"dudeyo", @"mattdipasquale", nil];
});
describe(@"-viewControllerWithTransaction:", ^{
it(@"calls -viewControllerWithTransaction:forceWeb:NO", ^{
[[client should] receive:@selector(viewControllerWithTransaction:forceWeb:)
withArguments:transaction, theValue(NO)];
[client viewControllerWithTransaction:transaction];
});
});
describe(@"-viewControllerWithTransaction:forceWeb:", ^{
__block UIApplication *app;
beforeEach(^{
app = [UIApplication sharedApplication];
});
context(@"forceWeb:NO", ^{
it(@"checks if app canOpenURL:transactionURL", ^{
NSURL *myURL = [NSURL URLWithString:@"https://my.com/"];
[[client should] receive:@selector(myURLWithPath:) andReturn:myURL];
[[app should] receive:@selector(canOpenURL:) withArguments:myURL];
[client viewControllerWithTransaction:transaction forceWeb:NO];
});
it(@"returns nil if canOpenURL:transactionURL", ^{
[[app should] receive:@selector(canOpenURL:) andReturn:theValue(YES)];
[[app should] receive:@selector(openURL:)];
[[client viewControllerWithTransaction:transaction forceWeb:NO] shouldBeNil];
});
it(@"returns a new MyViewController if not canOpenURL:transactionURL", ^{
[[app should] receive:@selector(canOpenURL:) andReturn:theValue(NO)];
[[[client viewControllerWithTransaction:transaction forceWeb:NO] should]
beKindOfClass:[MyViewController class]];
});
});
context(@"forceWeb:YES", ^{
it(@"bypasses canOpenURL:transactionURL check", ^{
[[app shouldNot] receive:@selector(canOpenURL:)];
[client viewControllerWithTransaction:transaction forceWeb:YES];
});
it(@"always returns a new MyViewController", ^{
[[[client viewControllerWithTransaction:transaction forceWeb:YES] should]
beKindOfClass:[MyViewController class]];
});
});
it(@"sets the returned MyViewController's transactionURL", ^{
NSURL *safariURL = [NSURL URLWithString:@"https://my.com/"];
[[client should] receive:@selector(safariURLWithPath:) andReturn:safariURL];
MyViewController *myController = [client viewControllerWithTransaction:transaction
forceWeb:YES];
[[myController.transactionURL should] beIdenticalTo:safariURL];
});
});
I get this error wherever I use functions inside the it block that take a list of arguments for one key. E.g.,, -[NSDictionary initWithObjectsAndKeys]
"Too many arguments provided to function-like macro invocation"
When something goes wrong, I get a line reference to the start of the block. It'd be nice to get a line reference to the actual line of code within the block.
When I test:
[[userId should] equal:[request objectForKey:@"user_id"]];
I get:
"VenmoClient -decodeSignedRequest: " FAILED, expected subject to equal (null), got "514417"
But, when I test:
[[[request objectForKey:@"user_id"] should] equal:userId];
I get:
failed: "VenmoClient -decodeSignedRequest: " FAILED, expected subject not to be nil
In the second case (where subject is nil), Kiwi should give a similar error to the first case so that I know what the subject was expected to equal.
Also, there's an extra space after -decodeSignedRequest:.
I'm getting a warning of a potential memory leak.
Should we call [objects release]
at the end of -containObjects:
?
https://github.com/allending/Kiwi/blob/master/Kiwi/KWContainMatcher.m#L89-103
If I do something like this:
// controller has "NSInteger offset;"
[[[controller valueForKey: @"offset"] should] equal: theValue(3)];
This fails because the returned offset is wrapped in an NSNumber, not in theValue. I have to do:
[[[controller valueForKey: @"offset"] should] equal: [NSNumber numberWithInt: 3]];
It would be better if it worked like this:
[[[controller valueForKey: @"offset"] should] equal: theValue(3)]; // -> returns true
[[[controller valueForKey: @"offset"] should] equalValue: 3]; // -> less to type
It would be great if this matcher worked for theValue's too:
[[theValue(controller.offset) should] equalValue: 3];
I'm not sure if I'm doing it right but I'm trying to stub an NSNumber property on a core data object.
Here's my test example:
it(@"should say 1 / ? with 1 point", ^{
mockCard = [KWMock nullMockForClass:[Card class]];
[mockCard stub:@selector(points) andReturn:[NSNumber numberWithInt:1]];
controller.card = mockCard;
[[controller.lblCount.text should] equal:@"1 / ?"];
});
And my source code:
-(void)setCard:(Card *)aCard{
if ([card.points intValue] == 1) {
lblCount.text = @"1 / ?";
}
}
Running this causes a SIGKIL
error in the writeObjectValueToInvocationReturnValue
method.
Am I missing something?
Say that I had a file with a bunch of test data in it (inputs and expected results). Something like the test vectors for SHA1, or, say, https://github.com/mzsanford/twitter-text-conformance. Is it possible to write something like:
context(@"file test cases", ^{
for( id input in [testData inputs] ) {
it([NSString stringWithFormat:@"should process %@", input], ^{
// ...
});
}
});
My quick test suggests that it's not (I never see these tests in the logs), and the mentions of "callsite" in the macro definitions for context
and it
make me kind of think it's not expecting to find these in a loop.
I'd like to move towards a structure similar to the RSpec project, with a core version that depends on nothing but Foundation, a Kiwi-iOS package that adds UIKit support (and eventually some nice UIKit-specific matchers?) and the same for Cocoa.
Following these instructions:
http://www.kiwi-lib.info/setup.html
I got 21 warnings with LLVM GCC 4.2 compiler
I was testing a category method, and I had named my class something like UIColor+MyAdditionsSpec.m
. The file was not picked up by the test runner.
I'm not sure if this is a bug in Xcode 4.2 , SenTestingKit, or Kiwi, unfortunately.
Removing the +
character from the spec filename made it work again.
Step 2 of setup http://www.kiwi-lib.info/setup.html says to change the compiler from GCC to:
LLVM compiler 1.x
It seems that these instructions may be slightly outdated because they seem to be for XCode 3, and also, LLVM compiler 2.0 is now the option... So, I'm wondering... what about LLVM GCC 4.2? That's what Xcode 4 had preselected. Is that good now? Maybe for Xcode 4, we should keep LLVM GCC 4.2? Or, should we still change it to LLVM compiler 2.0?
I tried to do should receive with arguments and one of the arguments is &error
. I even wrapped it in theValue()
, and that still didn't work.
The error just said something like, "expected blah blah 1 time, but received it 0 times." It'd be nice if Kiwi showed you what it did receive (even if it received the same message with different arguments).
Anyone have a demo of a functioning core data stack running on kiwi? For whatever reason, attempting this with the iOS Simulator confuses the hell out of the directory paths when it tries to put a persistent store in the appropriate app folder. Can't tell if this is specific to Kiwi yet, the debugging process is inconclusive so far. thought I'd see if anyone has a working rig already.
EDIT
Unbeknownst to @MattDiPasquale, he helped me with this from a post on StackOverflow, suggesting folks use NSLibraryDirectory instead of NSDocumentDirectory. This worked like a charm. However, I'll be damned if I can figure out where he has a switch for that in CocoaPlant's specs ... To me it looks like it doesn't ever try to create a persistent store in the library directory at all, and it just works ... weird.
In my NSManagedObject subclasses, I typically declare @properties from the header as @dynamic in the implementation. I've tried stubbing these properties with Kiwi, but it just crashes, so it would seem as though stubbing dynamic properties is not supported. Is there any way to stub them?
Given the implementation below:
// NSMutableDictionary+Additions.h
@interface NSMutableDictionary (Additions)
- (void)setOrRemoveObject:(id)anObject forKey:(id)aKey;
@end
// NSMutableDictionary+Additions.m
#import "NSMutableDictionary+Additions.h"
@implementation NSMutableDictionary (Additions)
- (void)setOrRemoveObject:(id)anObject forKey:(id)aKey {
if (anObject) {
[self setObject:anObject forKey:aKey];
} else {
[self removeObjectForKey:aKey];
}
}
@end
When I run the following spec:
// NSMutableDictionary+AdditionsSpec.m
#import "NSMutableDictionary+Additions.h"
#import "Kiwi.h"
SPEC_BEGIN(NSMutableDictionary_AdditionsSpec)
describe(@"NSMutableDictionary+Additions", ^{
describe(@"-setOrRemoveObject", ^{
__block NSMutableDictionary *aDict = nil;
beforeEach(^{
aDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"object", @"key", nil];
});
afterEach(^{
[aDict release];
});
it(@"sets object if not nil", ^{
id anObject = @"non-nil object";
id aKey = @"non-nil key";
[[aDict should] receive:@selector(setObject:forKey:) withArguments:anObject, aKey];
[aDict setOrRemoveObject:anObject forKey:aKey];
});
});
});
SPEC_END
Then, I get Warning: Unable to restore previously selected frame
And, the test execution hangs & loops and my computer over-heats until I stop them from running.
I initially tried to make aDict
a mock, but I was getting an error like setOrRemoveObject:forKey called but not expected, and I didn't feel like setting that expectation explicitly, but maybe I'll go back and do that instead. What do you recommend I do here?
I added a UILabel to one of my views and although it worked in the iPhone simulator it blew up in kiwi halting the thread. It happened on the line:
UILabel *label = [[[UILabel alloc] init] autorelease];
I narrowed it down to the init, as [UILabel alloc] did not cause the app to crash.
Is this a bug in kiwi or is there something I've failed to load? As far as I know it did not crash on init of other UIKit objects.
Thanks
Is it possible to enable --format doc to output even tests that pass? and -c to print them in color?
With OCUnit, you can check & uncheck actual test methods, but with Kiwi, you can only check & uncheck spec files.
Please provide proper test log output (expect a pull request if I come around to it) where every example gets its own log string, regardless of success or failure. Currently, only failures are reported.
Hello, I'm testing my code that publishes a new object to the server with RestKit and expects that a serverID should be assigned in the background. Each objects starts with serverID == 0
and I'm checking that after a call to publish serverID was assigned a non-zero value.
it(@"should be able to retrieve previously saved objects from server", ^{
newTrip.name = @"Retrieved from server";
NSManagedObjectID *newTripID = [newTrip objectID];
[newTrip save];
NSUInteger originalServerID = [newTrip.serverID intValue];
[[theValue(originalServerID) should] equal:theValue(0)];
// Publishing newTrip to the server; an assigment to newTrip.serverID should happen in the
// background but will not be propagated to current NSManagedObjectContext
[newTrip publish];
// Wait till we get a server id from server
__block Trip* serverTrip = nil;
dispatch_after(DISPATCH_TIME_NOW+0.3*NSEC_PER_SEC,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSManagedObjectContext *newContext = getContext();
serverTrip = (Trip *)[newContext objectWithID:newTripID];
});
[[theObject(&serverTrip) shouldEventually] beNonNil];
NSUInteger tripServerID = [[serverTrip serverID] intValue];
NSLog(@"Got server id for server trip: %u %@", tripServerID, serverTrip);
[[theValue(tripServerID) should] beGreaterThan:theValue(0)];
// Now that we have a Server ID, we can post a new request
__block Trip* anotherServerTrip = nil;
loadRequestAtPath([NSString stringWithFormat:@"/trip/%u",tripServerID],
^(id result, NSError *error) {
anotherServerTrip = (Trip *)result;
});
[[theObject(&anotherServerTrip) shouldEventually] beNonNil];
[[anotherServerTrip.serverID should] equal:theValue(tripServerID)];
[[anotherServerTrip.name should] equal:[newTrip name]];
});
My problem is that Kiwi fails on both of the [[theObject(..) shouldEventually] beNonNil]
calls, while the consecutive tests succeed and NSLog confirms that serverTrip object is in fact not nil:
2011-09-20 14:32:31.730 TripPlanner iPhone[91803:11c03] Got server id for server trip: 35 <Trip: 0x71427b0> (entity: Trip; id: 0x74c4d40 <x-coredata://B2A3F8CC-0F1B-49A9-A9B8-C8195CAE063E/Trip/p144> ; data: {
name = "Retrieved from server";
picture = nil;
pointsOfInterest = "<relationship fault: 0xbc93c30 'pointsOfInterest'>";
serverID = 35;
timeStamp = nil;
})
I could be missing something simple, as I tried to get the correct shouldEventually
usage from the Examples, but it looks like some kind of Kiwi-related issue to me.
I'm on Xcode 4.2 / iOS 5.0 b7 if that matters, and I've added Kiwi as a static library following guidance in #42.
Any help would be greatly appreciated!
I just added Kiwi to a project, created a sample spec, and tried to run the tests. The build failed with the following error:
"Inconsistent instance variable specification"
The problem is happening in this code:
@implementation KWExampleGroup { NSArray *contextNodeStack; id<KWExampleNode> exampleNode; BOOL passed; }
What can I do to resolve this? I'm using Xcode 4.1 with iOS SDK 4.3 and the LLVM GCC 4.2 compiler.
The provide feedback link on http://www.kiwi-lib.info/download.html is broken.
perhaps it should point to: https://github.com/allending/Kiwi/issues/new
Also, link to google group on http://www.kiwi-lib.info/help.html is broken.
And it says help me at the bottom, but maybe that should be changed to help yourself. :) since it's free now...
I apologize if this isn't clearly expressed but ...
I don't know if this exists yet and I just don't see how to do it, but it would be nice to have a way to indicate a test and the corresponding functionality has not yet been implemented.
When I use Kiwi I often will stub out several it's at once and then go back and write each test and make them pass. But while I'm first approaching a new feature I might think of many things that I want to be true in a particular context.
I don't know the syntax but something like
it(@"should default to the system sounds folder", ^{
[self todo];
});
And this would count as an unimplemented test and not be reflected in the pass or fail but probably still in the total.
Sometimes when using -receive:andReturn:
, I get warning: Unable to restore previously selected frame.
, and I have to press Command-. to stop the test.
spec:
// warning: Unable to restore previously selected frame.
specify(@"base64DecodedString", ^{
NSString *string = @"hello world";
NSData *data = [@"hellow world" dataUsingEncoding:NSASCIIStringEncoding];
[[string should] receive:@selector(base64DecodedData) andReturn:data];
[[[string base64DecodedString] should] equal:@"hello world"];
});
code:
@implementation NSString (VenmoBase64)
- (NSString *)base64DecodedString {
return [[NSString alloc] initWithData:[self base64DecodedData] encoding:NSASCIIStringEncoding];
}
- (NSData *)base64DecodedData {
const char *string = [self cStringUsingEncoding:NSASCIIStringEncoding];
NSInteger inputLength = self.length;
if (string == NULL/* || inputLength % 4 != 0*/) {
return nil;
}
while (inputLength > 0 && string[inputLength - 1] == '=') {
inputLength--;
}
NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t *output = data.mutableBytes;
NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
while (inputPoint < inputLength) {
char i0 = string[inputPoint++];
char i1 = string[inputPoint++];
char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will decode to \0 */
char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';
output[outputPoint++] = (_base64DecodingTable[i0] << 2) | (_base64DecodingTable[i1] >> 4);
if (outputPoint < outputLength) {
output[outputPoint++] = ((_base64DecodingTable[i1] & 0xf) << 4) | (_base64DecodingTable[i2] >> 2);
}
if (outputPoint < outputLength) {
output[outputPoint++] = ((_base64DecodingTable[i2] & 0x3) << 6) | _base64DecodingTable[i3];
}
}
return data;
}
@end
This feature is a must for me.
Is it possible to run the specs in Xcode w/o launching the iOS Simulator? Would be faster...
I don't even know how to do this with OCUnit though...
http://stackoverflow.com/questions/6165222/ocunit-how-to-run-tests-without-launching-iphone-simulator
Right now forwarding works in most cases, but there are scenarios that kill it, and using libffi would make support for arm + x86 much easier.
Is there any way to create instance variables inside the SPEC_BEGIN block? From the look of the macro, it looks like there isn't, but the beforeAll methods would imply that there must be such a way. Or must I forego the SPEC_BEGIN block and do an actual class declaration?
beforeAll does not do what you expect it to now that each case is now independent. Thoughts? Do people even use it?
cd ~/Projects/iOS/Kiwi
git merge pivotal/Cedar master
:)
Seriously though. Have you heard of Cedar? https://github.com/pivotal/Cedar
Looks like both Cedar & Kiwi share a common interest: Bringing RSpec to Objective-C.
Is it possible we could join forces? Take the best of both worlds?
Matt
When I'm writing code within a describe or it block, it'd be nice to get the same kind of code completion I get normally from Xcode.
Convert OCUnit tests that test Kiwi into Kiwi specs.
Tests halt when I try inside an it block:
[navController pushViewController:viewController1 animated:NO]; // breaks for some reason
Matt
In Rspec, you can leave out the description for it & specify. E.g.:
specify { "hello".should == "hello" }
We should be able to do this in Kiwi too. E.g.:
specify(^{[[@"hello" should] equal:"hello"]});
Here's how we could create the description as a default argument.
http://stackoverflow.com/questions/1472138/c-default-arguments/1472151#1472151
Kiwi is too good.
Yes, that's the issue...
No, the issue is... why doesn't anyone know about this lib!?
What are you doing hiding this from everyone, sir? :P
Let's tell the world!
Matt
P.S. I just spent a few hours mocking (Yes, I mocked alloc
, :)), stubbing, expecting... Wow... It's awesome! A breeze to set up. Man...
Thank you.
Keep it up! :)
GHUnit offers this:
GHTestLog(@"I can log to the GHUnit test console: %@", a);
http://gabriel.github.com/gh-unit/_examples.html#ExampleTestCase
https://github.com/gabriel/gh-unit/blob/master/Classes/GHTest/GHTestRunner.m#L170-177
I'm getting a bunch of errors in runtime.h like the following when I try to run my unit tests (which include Kiwi) on Xcode 4.1 on OS X Lion. The tests ran fine on previous versions of Xcode and even work on the Xcode 4.2 Developer Preview. Here's one of the errors I'm seeing:
/usr/include/objc/runtime.h:86: error: expected declaration specifiers before 'OBJC_ARC_UNAVAILABLE'
There are a whole lot more - 590 errors in my project. Below are some more examples - I'm not sure of the best way to report this.
/usr/include/objc/runtime.h:89: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'OBJC_ARC_UNAVAILABLE'
/usr/include/objc/runtime.h:92: error: storage class specified for parameter 'object_getClass'
/Users/josh/Code/goodmeasures/iphone/Kiwi/Kiwi/KWFormatter.h:9: error: expected declaration specifiers before 'interface'
I should also mention that I created a new project with Xcode 4.1 that included unit tests (but no Kiwi) and the tests ran fine.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.