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

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.

Related

Having separate schemes for test targets in Xcode?

We have the following project structure:
Workspace:
- app project
- cocoapods project
App scheme:
- app target (run)
- ui test target (test)
- unit test target (test)
After upgrading to Xcode 10, Xcode insists on building the entire project, including pods and ui tests, every time I run a single unit test, which is a quite heavy and slow process.
If i create a seperate scheme which only include the unit and/or ui tests, it only rebuilds the tests when I run them. Just as I want.
However, as they are no longer member of the main app scheme, I can no longer press Test on the main scheme, as it no longer contains test targets.
My question is then: Is it normal or recommended to have seperate schemes for tests, or can I prevent the entire project from being rebuild in another way, when running a single unit test?
(note: I have set the Host Application setting to None on the unit tests, so I don't get why it always builds the entire project anyway?)
Why not both? In your "Test All the Things" scheme, add each test target. This scheme should be shared.
But when I'm working in one target, I make a scheme for it alone. (More accurately, AppCode creates one for me.) Such schemes are not shared.

Optimizing build time in Android Studio

I've tried building it:
parallel (helps a bit)
daemon=true
preDexLibraries true/false ( no big difference )
incremental true
offline
It takes >40s EVERY time. It doesn't matter if I change anything or not. Building it after "gradle clean" takes >50s.
I hope that I'm doing something wrong. Eclipse/ant could build consecutive builds WITH CHANGES in <10s.
Any help how to bring this <10s appreciated.
Yes, we have a lot of modules, some jar libraries, some maven dependancies. Still don't get why would it take >40s for two consecutive builds with no changes.
Gradle used: 2.2.1
Android studio: not really relevant, usually building it only with Gradle.
EDIT: adding some profiling logs.
:app:dexProjDebug 22.541s
:app:shrinkProjDebugMultiDexComponents 4.279s
:app:compileProjDebugJava 3.478s
:app:packageProjDebug 2.591s
:app:processProjDebugResources 2.590s
:app:packageAllProjDebugClassesForMultiDex 2.536s
:app:createProjDebugMainDexClassList 2.126s
You need to properly define inputs and outputs even for library projects with source code. (Gradle Documentation). Do you get UP-TO-DATE message when you rebuild second time onwards?
If you have no changes to the other modules, you can build the app itself using gradlew :app:build. This will eliminate the time Gradle spends on building the other modules. You can build any module separately like this as well, using gradlew :moduledirectoryname:build. If you need to build one module and the app, you can execute both tasks at once to avoid going through Gradle's configuration stage twice: gradlew :app:build :moduledirectoryname:build
If possible, update to Gradle 2.4. It's significantly faster (claiming 20-40%).
One of the most significant build time reducers is the preDex task. Check whether preDex is running in your build. It increases build time the first time you run it, but dramatically reduces build times in subsequent builds, as most of your SDKs and libraries will already be dexed. Note however that it won't run under some conditions, e.g. if you use multidex.
Btw Google are well aware of build times with Gradle and Android Studio and are going to introduce significant improvements in upcoming releases, including Jack and Jill which will allow compiling from source code directly to dex. You can already try to experiment with them - see here: http://tools.android.com/tech-docs/jackandjill.
Also worth watching this video from recent Google I/O: https://youtu.be/f7ihSQ44WO0?t=327
Download Genymotion emulator. It is very fast and good to run android apps. It will save you a lot of time.
Here is the link - GenyMotionDownload

Unit Tests are always "successful" after adding OCMock

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.

TeamCity Multi-Part Build - How to checkout the code just once

I am trying to create 1 package with multiple build configurations. The first will checkout the code, build it (Solution File configuration), and run nunit tests. If that succeeds, another will then build in release mode. If that succeeds, a final script witll package up the output, and mark it as an artifact.
The problem I'm having is that I don't know how to tell TeamCity not to create new directories for each step, and as a result, the steps are failing. Is there a setting for this? It seems like the dependencies tab would be an appropriate place to look, but I don't seem to understand the instructions, and my tinkering so far has been fruitless.
I basically skipped most of the TeamCity workflow, and instead used a scripting language to handle all of this. (I used Rake and Albacore, which I highly recommend for .net projects)
I'd caution you not to use powershell w/ TeamCity. You have to wrap everything in .bat file, which is fairly excruciating.
So the result, is that I have 1 checkout, and everything builds from this point. It's drastically cut down the amount of time required for the builds, though perhaps that wouldn't be the case if I had a lot of agents available.

Pre-build task - deleting the working copy in CruiseControl.NET

I'm currently in the process of setting up a continuous integration environment at work. We are using VisualSVN Server and CrusieControl.NET. Occasionally a build will fail and a symptom is that there are conflicts in the CruiseControl.NET working copy. I believe this is due to the way I've setup the Visual Studio solutions. Hopefully the more projects we run in this environment the better our understanding of how to set them up will be so I'm not questioning why the conflicts happen at this stage. To fix the builds I delete the working copy and force a new build - this works every time (currently). So my questions are: is deleting the working copy a valid part of a continuous integration build process, and how do I go about it?
I've tried solutions including MSTask and calling delete from the command line but I'm not having any luck.
Sorry for being so wordy - good job this is a beta :)
Doing a full delete before or after your build is good practice. This means that there is no chance of your build environment picking up an out of date file. Your building exactly against what is in the repository.
Deleting the working copy is possible as I have done it with Nant.
In Nant I would have a clean script in its own folder outwith the one I want to delete and would then invoke it from CC.net.
I assume this should also be possible with a batch file. Take a look at the rmdir command http://www.computerhope.com/rmdirhlp.htm
#pauldoo
I prefer my CI server to do a full delete as I don't want any surprise when I go to do a release build, which should always be done from a clean state. But it should be able to handle both, no reason why not
#jamie: There is one reason why you may not be able to do a clean build every time when using a continuous integration server -- build time. On some projects I've worked on, clean builds take 80+ minutes (an embedded project consisting of thousands of C++ files to checkout and then compile against multiple targets). In this case, you have to weigh the benefit of fast feedback against the likelihood that a clean build will catch something that an incremental build won't. In our case, we worked on improving and parallelizing the build process while at the same time allowing incremental builds on our CI machine. We did have a few problems because we weren't doing clean builds, but by doing a clean build nightly or weekly you could remove the risk without losing the fast feedback of your CI machine.
If you check out CC.NET's jira there is a patch checked in to implement CleanCopy for Subversion which does exactly what you want and just set CleanCopy equal to true inside your source control block just like with the TFS one.
It is very common and generally a good practice for any build process to do a 'clean' before doing any significant build. This prevents any 'artifacts' from previous builds to taint the output.
A clean is essentially what you are doing by deleting the working copy.
#Brad Barker
Clean means to just wipe out build products.
Deleting the working copy deletes everything else too (source and project files etc).
In general it's nice if you're build machine can operate without doing a full delete, as this replicates what a normal developer does. Any conflicts it finds during update are an early warning to what your developers can expect.
#jamie
For formal releases yes it's better to do a completely clean checkout. So I guess it depends on the purpose of the build.

Resources