Unit Tests are always "successful" after adding OCMock - cocoa

I would like to use OCMock in my Cocoa project's unit tests. I have downloaded the latest version of OCMock (2.0.1) and copied the OCMock.framework into my project's directory. In Xcode, I have added the framework to the unit test target's link phase. I have then added some code that uses OCMock's classes.
From then on out, all unit tests are reported as "successful" - green light, no errors or warnings. Even after introducing STFail calls, Xcode claims "Test succeeded". Placing a breakpoint in arbitrary test methods reveals that none of them are executed.
The issue persists if I comment out the code using OCMock, including the import directives.
The issue vanishes - i.e., the STFails start failing again - when I remove OCMock from the link phase.
This is similar to another question I've asked before, but not exactly the same: In this case, the info in the Log Navigator shows no errors. What could be causing this behavior? What can I do to diagnose the matter?

It turns out I was missing a Copy Files build phase for the framework, which apparently may lead to a variety of issues.
This works for me:
Add a Copy Files phase to the unit test target's build phases. I positioned it right before the Run Script phase, making it the second-to-last one.
Drag the OCMock.framework item from the project navigator onto the phase in order to add it; adding it using the + button doesn't work in Xcode 4.6 (maybe because frameworks are directories?).
Set the phase's destination to "Frameworks".
In the unit test target's build settings, look for Runpath Search Paths and add the entry #loader_path/../Frameworks.
This way, the unit test executable will be able to find the framework at runtime. Note that you can also use "Products Directory" as the destination of the Copy Files phase, in which case you can skip the fourth step.

Related

How does IntelliJ decide what bytecode (classes) to use when running a maven app?

Questions
My questions are:
(Q) When running an app in the IntelliJ debugger, how does IntelliJ decide which bytecode to use ?
(Q) Does IntelliJ use whatever maven build plugin is being used or simulate it?
(Q) If multiple conflicting versions of code are being used (see mvn dependency:tree -Dverbose), how does IntelliJ decide which version of the code to use?
(Q) Where is the JAR file that IntelliJ creates so I could inspect it to see what versions of classes were used?
(Q) Is the process of selecting classes to use any different when running vs debugging?
Note: This question is being directed to IntelliJ's support staff as well as the SO community.
Background
I have an app that has been very problematic with IntelliJ with regards to picking the desired classes when running the application. 
The app is a Java Executable Jar that has been packaged with the maven-assembly-plugin.  It is not a SpringBoot application.
The problem stems from IntelliJ picking different class files than the maven-assembly-plugin which copies all of these classes (from all of the dependent jar files) into a single jar file. Naturally, only one version of a class can exist in the jar app (I believe the first class copied wins and the others are ignored).
IntelliJ (AFAIK) has no way of knowing what version of what class will be put into the JAR without knowing how the maven-assembly-plugin is implemented; So I'm looking for this answer.
Understanding the Question
To explain, see the example I created to understand how the maven-shade-plugin works. See Is there a sample project in github that shows how to use the maven-shade-plugin?. It's not a perfect fit for my problem/question, but it is in the public domain and it's close enough.
I'll frame my question based on the helloworld example. The helloworld.pom depends directly on loglib:2.0.0 so I would expect IntelliJ to select and use that version when compiling and running the application.  
The problem (code changes not being picked up)
The problem I ran into was when I changed the helloworld/pom.xml file to depend on loglib:2.1.0-SNAPSHOT and IntelliJ did not pick up the code changes and used a previous version of the dependency even though the source code was loaded inside of IntelliJ and the loglib/pom.xml file was changed to be version 2.1.0-SNAPSHOT.
The application is run by specifying the main class of the application com.steranka.play.HelloWorldApp. The Run/Debug configuration is:
NOTE: I've done this exact thing many/many times and it's always worked, so I was puzzled. I also tried to reproduce the problem with a sample example and could not reproduce it. IntelliJ worked flawlessly picking up changes as it has always done in the past.
Trying to fix the problem (bytecode not matching source code)
I went through the list of things I've done in the past but after they were all completed, the problem remained.  The list of steps I followed included:
(1) Rebuilt the project (which included helloworld and loglib packages). Rebuild was done inside of IntelliJ. Nope.
(2) Verify that the correct maven dependency loglib:2.1.0-SNAPSHOT was being used in helloworld module, and that it shows up in the Maven Tools dependency list. 
(3) Clicked Reload all Maven Projects - run from Maven Tool. 
After IntelliJ restart, I made a change to a log.info() statement in the loglib:2.1.0-SNAPSHOT module ran my program and my changes to the log statement did not appear, only the previous version of the log message appeared.
This is the crux of the problem, and reason for my question.  Where is IntelliJ getting the bytecode that it is running? Is it from loglib/target/classes/* directory (this is my belief), or from maven .m2/repository/ ... / loglib:2.0.0-SNAPSHOT.
(3) I put a breakpoint on the log statement (that I changed) and ran the app in Debug mode and IntelliJ stopped on the log statement when I stepped over the statement the wrong log message was printed.  This is when I knew the bytecode IntelliJ was executing did not match the source code.
Detailed steps that reproduced the problem
To be clear I'll give timestamp versions because I don't know exactly what POM versions were being used:
T1: Starting with line that says: log.info("orig message");
T2: I changed the message to log.info("orig message - change1");
T3: IntelliJ did not pick up my change and log/console shows orig message
T4: I added some lines to the source code (multiple log statements)
     log.info("this is strange")
     log.info("why isn't this working")
T5: I put a breakpoint on the line why isn't this working and the breakpoint symbol appeared
T6: However, when I ran the program and IntelliJ stopped at the first breakpoint (orig message - change1) and when it stopped the 2nd breakpoint symbol was greyed out (indicating that the debugger could not stop on that line). 
T7: I stepped and IntelliJ was obviously running different code because the original message appeared instead of the changed message.
More Questions
(Q) When the IntelliJ debugger shows code that doesn't match what is being actually executed, how can I track down what code is actually being used? The answer to my previous questions should answer this.
The observable things I know to look at are:
The Project Settings modules.
The maven tool modules list and the dependencies.
The External Libraries list in the Project Tool.
The target/.jar and target/.classes files.
Settings - java compiler used, maven used,
Common Reasons for this problem (bytecode not matching source code in debugger)
Reason 1: The most common reason for the above problem (in my past) has been making a code change in some module (say loglib when the loglib/pom.xml is at version 2.1.0-SNAPSHOT) and forgetting to update helloworld/pom.xml to refer to the -SNAPSHOT version. In my case I performed this check.
Reason 2: Years ago debuggers did not automatically compile code before the code was run, and this let to the problem whereby the bytecode being used matched the last time the file was compiled. The fix was/is simple, recompile the code and update the *.class file contains your code changes and the debugger code matches the bytecode that is being executed.
How to Reproduce the problem
The maven-shade-example (referred to above) can be used to reproduce the problem where the code shown in the debugger is not used at runtime.
git clone git#github.com:steranka/maven-shade-example.git
cd maven-shade-example
git checkout feature/fixing-problem-another-way
mvn clean install
java -jar helloworld\target\helloworld-1.0.0.jar
The output is:
Hello World!
What's up, Sam
Hello, Sam
Goodbye, Sam
But if you try to open this project inside IntelliJ and build and run it, you'll get an error. To run this, I right clicked on the hello word application and selected Run HelloWorldApp.main() (or Debug).
Hello World!
What's up, Sam
Exception in thread "main" java.lang.NoSuchMethodError: 'java.lang.String com.steranka.play.LogIt.sayHello(java.lang.String)'
at com.steranka.play.GoodFeature.sayGoodbye(GoodFeature.java:6)
at com.steranka.play.HelloWorldApp.main(HelloWorldApp.java:15)
What makes this un-nerving is the debugger jumps to the correct code if you click on the method, it just doesn't use that method at runtime.
The runtime configuration inside IntelliJ is:
#CrazyCoder points out that IntelliJ will run the JAR file created using mvn clean install in the helloworld\target\helloworld-1.0.0.jar if you create a run configuration that says to use Java.
When I created a run configuration to use the Jar file, then IntelliJ's debugger properly executed the application and stepped into the correct files. That configuration looks like this:
When I tried this solution on the actual code causing problems, it also worked. Strangely enough (to me) after switching to the JAR configuration and successfully running, I switched back to my Main class configuration and it also worked! So toggling between the two configurations might work for others as it did for me.
#CrazyCoder also points out that there is an outstanding bug/feature request with IntelliJ that asks for better support of the maven-shade-plugin. See https://youtrack.jetbrains.com/issue/IDEA-266746
#Thorbjørn Ravn Andersen states that IntelliJ emulates Maven so in general the behavior between building and running inside IntelliJ should match what happens with Maven.

XCTest: How do I prevent Xcode from needlessly recompiling my project if I'm only making changes to my test Target

My Xcode project is very large, in terms of number of source files, and lines of code.
When I make a change to only the XCTest code, and hit run on a single test, a single test file, or even the whole test suite, Xcode re-compiles my host application first, even if no files have changed in the host application. It does so every time I make any change to any test file.
This is posing an efficiency challenge with writing tests, because small adjustments in the test code take a long time to re-run and re-validate. (upwards of 3 minutes per run - yes it's that big of a project, and we are already taking many steps to cut down the build time, by inspecting the build logs, etc...)
Using Xcode 10.3 with Swift 4.2
the tests are using:
#testable import MyModuleName
Is there a way I can prevent Xcode from re-building the whole project, if I've only changed tests?
I found the problem.
We have some custom scripts under the Project's Build Phases section that actually change some of the compilable assets in the codebase. We also have a Carthage dependency copy stage.
Commenting out both of these stages from Build phases makes it so that the whole project does not recompile when only changing tests. These scripts were actually making changes to the compilable code, making XCode force re-compilation.
Moral of the story: Check your build phases for any steps that could be modifying your source code, including possibly resource files that are part of the target. We will try to do this in a more automated way in the future, without having to comment out these build steps.

Checked Out New Project in XCode 6.1 but XCTest and other libraries are missing

Today I checked out a new copy of stable project from gitHub to my home computer using Xcode 6.1. After doing so, I see that many of the frameworks and libraries, including XCTest, are missing (shown in red). I have added Framework and Header Search Paths, but they are still not found.
To make things stranger, I can build the project to a simulator or device, but when I try to run an individual test, I get clang or missing file error for the libraries/frameworks shown in red.
As it turns out, the reason for my errors was that I had not run "Build for Testing" before trying to run the individual Unit Tests. As such, the proper library dependencies had not been generated.

Xcode 3 Product depends on itself. Audio Unit Effects copy file issue

For reasons beyond my control, I am using Xcode 3 and attempting to build a crude Audio Unit effect. While setting up the configuration for my project, I tried to set up a 'Copy Files' build phase in order to have the Component Manager be able to find my unit. When I dragged the Unit's component into the new Copy Files build phase and tried to to build the project, I am getting the follow error:
Check Dependencies: Product depends on itself. THis target might include it's own product.
I tried deleting the component file from my Copy Files build phase, and I was able to build the project successfully, however when I run auval -a in the terminal, the Component Manager does not find my effect unit.
How can i fix this?... is it even fixable in Xcode 3?
To accomplish build and install in one build invocation, you can either
a) create a separate target which defines the AU as a dependency and performs the copy (and any other post-build steps)
or b) set the INSTALL_PATH to the components directory and touch the AU as the last build step

Dynamically adding resources to XCode project, always one cycle behind

I need to assemble resources for an application depeding on XCode build settings. The easiest way to achieve this, is through a build script phase. Although this works, this somehow always builds my target with resources one version lagging (a second build is needed to get things really up-to-date).
The Resources folder is a reference to a folder in which my script (or rather, custom built command line tool called from script) copies the appropriate resources. The run script build phase is the first (topmost) phase in my target.
A solution I've found on the web somewhere, is to create an "External Target" and add that to the original target's build phases (by dragging the External target onto the original target). This does indeed seem to fix the "one version behind" issue, but I cannot seem to get the current target's environment variables to be passed to this "External target".
Why is XCode not including the just updated resources? What other alternatives are there?
You could try to define an internal target (say, "ResourceTarget") and make the main target dependent on ResourceTarget. Then let your script run in the script build phase of ResourceTarget, so the resources are all updated when the second target is build.
That way, environment variables should be the same.

Resources