Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

GHUnit gem.

  • Loading branch information...
commit 3b4d532a5e2dd098fb0af23c4e6f12e1b052ec03 1 parent 71d3d2c
@gabriel gabriel authored
View
1  .gitignore
@@ -13,3 +13,4 @@ GHUnit.docset
*.xcuserdatad
Project-iOS/GHUnitIOS.xcodeproj/xcuserdata
Project-iOS/GHUnitIOS.xcodeproj/project.xcworkspace/xcuserdata
+Gem/test/tmp
View
8 Gem/Rakefile
@@ -0,0 +1,8 @@
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+ t.libs << 'test'
+end
+
+desc "Run tests"
+task :default => :test
View
35 Gem/bin/ghunit
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require 'slop'
+require 'ghunit'
+require 'colorize'
+
+opts = Slop.parse do
+ banner "Usage: ghunit [options]"
+
+ on :n, :name=, "Project name"
+ on :p, :path=, "Project path, defaults to <Project Name>.xcodeproj", argument: :optional
+ on :t, :test_target=, "Test target name, defaults to Tests", argument: :optional
+
+end
+
+if !opts[:name]
+ puts " "
+ puts "Need to specify project name.".red
+ puts " "
+ puts opts.to_s
+ puts " "
+ exit 1
+end
+
+target_name = opts[:name]
+project_path = opts[:path] || "#{target_name}.xcodeproj"
+test_target_name = opts[:test_target] || "Tests"
+
+project = GHUnit::Project.open(project_path, target_name, test_target_name)
+if project
+ puts " "
+ project.create_test_target
+end
+
+
View
BIN  Gem/ghunit-1.0.0.gem
Binary file not shown
View
16 Gem/ghunit.gemspec
@@ -0,0 +1,16 @@
+Gem::Specification.new do |s|
+ s.name = "ghunit"
+ s.version = "1.0.0"
+ s.executables << "ghunit"
+ s.date = "2014-01-29"
+ s.summary = "GHUnit"
+ s.description = "Utilities for GHUnit iOS/MacOSX test framework."
+ s.authors = ["Gabriel Handford"]
+ s.email = "gabrielh@gmail.com"
+ s.files = ["lib/ghunit.rb", "lib/ghunit/project.rb", "lib/ghunit/templates/Podfile", "lib/ghunit/templates/Test.m", "lib/ghunit/templates/main.m"]
+ s.homepage = "https://github.com/gh-unit/gh-unit"
+ s.license = "MIT"
+ s.add_runtime_dependency "xcodeproj"
+ s.add_runtime_dependency "slop"
+ s.add_runtime_dependency "colorize"
+end
View
2  Gem/install.sh
@@ -0,0 +1,2 @@
+gem build ghunit.gemspec
+gem install ghunit
View
4 Gem/lib/ghunit.rb
@@ -0,0 +1,4 @@
+
+module GHUnit; end
+
+require 'ghunit/project'
View
204 Gem/lib/ghunit/project.rb
@@ -0,0 +1,204 @@
+require 'xcodeproj'
+require 'xcodeproj/ext'
+require 'fileutils'
+require 'logger'
+require 'colorize'
+
+class GHUnit::Project
+
+ attr_reader :project_path, :target_name, :test_target_name, :logger
+
+ attr_reader :project, :main_target
+
+ def initialize(project_path, target_name, test_target_name, logger=nil)
+ @target_name = target_name
+ @project_path = project_path
+ @test_target_name = test_target_name
+ @logger ||= begin
+ logger = Logger.new(STDOUT)
+ logger.formatter = proc do |severity, datetime, progname, msg|
+ case severity
+ when "ERROR"
+ "#{msg}\n".red
+ when "DEBUG"
+ "#{msg}\n".green
+ else
+ "#{msg}\n"
+ end
+ end
+ logger
+ end
+ end
+
+ def open
+ if !File.exists?(project_path)
+ logger.error "Can't find project path at #{project_path}"
+ return false
+ end
+
+ @project = Xcodeproj::Project.open(project_path)
+
+ # Find the main target for the test dependency
+ @main_target = project.targets.select { |t| t.name == target_name }.first
+ if !@main_target
+ logger.error "No target with name #{target_name}"
+ return false
+ end
+
+ true
+ end
+
+ class << self
+ def open(project_path, target_name, test_target_name, logger=nil)
+ project = GHUnit::Project.new(project_path, target_name, test_target_name, logger)
+ if project.open
+ project
+ else
+ nil
+ end
+ end
+ end
+
+ def find_test_target
+ project.targets.select { |t| t.name == test_target_name }.first
+ end
+
+ # Create the test target and setup everything
+ #
+ def create_test_target
+ Dir.chdir(File.dirname(project_path))
+ FileUtils.mkdir_p(test_target_name)
+
+ # Write the Tests-Info.plist
+ test_info = {
+ "CFBundleDisplayName" => "${PRODUCT_NAME}",
+ "CFBundleExecutable" => "${EXECUTABLE_NAME}",
+ "CFBundleIdentifier" => "tests.${PRODUCT_NAME:rfc1034identifier}",
+ "CFBundleInfoDictionaryVersion" => "6.0",
+ "CFBundleName" => "${PRODUCT_NAME}",
+ "CFBundlePackageType" => "APPL",
+ "CFBundleShortVersionString" => "1.0",
+ "CFBundleVersion" => "1.0",
+ "LSRequiresIPhoneOS" => true,
+ "UISupportedInterfaceOrientations" => ["UIInterfaceOrientationPortrait"]
+ }
+ test_info_path = File.join(test_target_name, "#{test_target_name}-Info.plist")
+ if !File.exists?(test_info_path)
+ logger.debug "Creating: #{test_info_path}"
+ Xcodeproj.write_plist(test_info, test_info_path)
+ else
+ logger.debug "#{test_info_path} already exists, skipping..."
+ end
+
+ test_target = find_test_target
+ if !test_target
+
+ # Create the test target
+ logger.debug "Creating target: #{test_target_name}"
+ test_target = project.new_target(:application, test_target_name, :ios, "7.0")
+ test_target.add_dependency(main_target)
+
+ create_test_file("main.m", template("main.m"), true)
+ create_test("MyTest")
+
+ else
+ logger.debug "Test target already exists, skipping..."
+ end
+
+ # Use same resources build phase as main target
+ # Have to compare with class name because of funky const loading in xcodeproj gem
+ resources_build_phase = main_target.build_phases.select { |p|
+ p.class.to_s == "Xcodeproj::Project::Object::PBXResourcesBuildPhase" }.first
+ test_target.build_phases << resources_build_phase if resources_build_phase
+
+ # Get main target prefix header
+ prefix_header = main_target.build_settings("Debug")["GCC_PREFIX_HEADER"]
+
+ # Clear default OTHER_LDFLAGS (otherwise CocoaPods gives a warning)
+ test_target.build_configurations.each do |c|
+ c.build_settings.delete("OTHER_LDFLAGS")
+ c.build_settings["INFOPLIST_FILE"] = test_info_path
+ c.build_settings["GCC_PREFIX_HEADER"] = prefix_header if prefix_header
+ end
+
+ # Create test scheme if it doesn't exist
+ logger.debug "Checking for Test scheme..."
+ schemes = Xcodeproj::Project.schemes(project_path)
+ test_scheme = schemes.select { |s| s == test_target_name }.first
+ if !test_scheme
+ logger.debug "Test scheme not found, creating..."
+ scheme = Xcodeproj::XCScheme.new
+ scheme.set_launch_target(test_target)
+ scheme.save_as(project_path, test_target_name)
+ else
+ logger.debug "Test scheme already exists, skipping..."
+ end
+
+ logger.debug "Saving project..."
+ project.save
+
+ check_pod
+ end
+
+ def template(name)
+ template_path = File.join(File.dirname(__FILE__), "templates", name)
+ File.read(template_path)
+ end
+
+ # Create a file with content and add to the test target
+ #
+ def create_test_file(file_name, content, force=false)
+ # Create main.m for test target
+ path = File.join(test_target_name, file_name)
+
+ if !force && File.exists?(path)
+ logger.info "Test file already exists, skipping"
+ end
+
+ logger.debug "Creating: #{path}"
+ File.open(path, "w") { |f| f.write(content) }
+
+ add_test_file(path)
+ path
+ end
+
+ # Add a file to the test target
+ #
+ def add_test_file(path)
+ test_target = find_test_target
+ if !test_target
+ logger.error "No test target to add to"
+ return false
+ end
+
+ tests_group = project.groups.select { |g| g.name == test_target_name }.first
+ tests_group ||= project.new_group(test_target_name)
+
+ test_file = tests_group.find_file_by_path(path)
+ if !test_file
+ test_file = tests_group.new_file(path)
+ end
+ test_target.add_file_references([test_file])
+ true
+ end
+
+ def create_test(name)
+ name = "#{name}.m" unless name.end_with?(".m")
+ path = create_test_file(name, template("Test.m"))
+ logger.debug "Created test: #{path}"
+ end
+
+ # Check the Podfile or just display some Podfile help
+ #
+ def check_pod
+ logger.info <<-EOS
+
+Add the following to your Podfile and run pod install.
+
+#{template("Podfile")}
+
+Make sure to open the .xcworkspace.
+
+EOS
+ end
+end
View
3  Gem/lib/ghunit/templates/Podfile
@@ -0,0 +1,3 @@
+target :Tests do
+ pod 'GHUnit'
+end
View
12 Gem/lib/ghunit/templates/Test.m
@@ -0,0 +1,12 @@
+#import <GHUnit/GHUnit.h>
+
+@interface MyTest : GHTestCase
+@end
+
+@implementation MyTest
+
+- (void)test {
+
+}
+
+@end
View
8 Gem/lib/ghunit/templates/main.m
@@ -0,0 +1,8 @@
+// This file auto-generated by ghunit gem
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, @"GHUnitIOSAppDelegate");
+ }
+}
View
71 Gem/test/test_ghunit.rb
@@ -0,0 +1,71 @@
+require 'test/unit'
+require 'ghunit'
+require 'fileutils'
+require 'zip/zip'
+
+class GHUnitTest < Test::Unit::TestCase
+
+ def unzip_file(file, destination)
+ Zip::ZipFile.open(file) do |zip_file|
+ zip_file.each do |f|
+ next if f.name =~ /__MACOSX/ or f.name =~ /\.DS_Store/ or !f.file?
+ f_path = File.join(destination, f.name)
+ FileUtils.mkdir_p(File.dirname(f_path))
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
+ end
+ end
+ end
+
+ def cleanup
+ FileUtils.rm_rf(File.join(File.dirname(__FILE__), "tmp"))
+ end
+
+ def tmp_dir
+ File.join(File.dirname(__FILE__), "tmp")
+ end
+
+ def root_dir
+ File.join(File.dirname(__FILE__), "..", "..")
+ end
+
+ def generate_empty_project_files
+ cleanup
+
+ FileUtils.mkdir_p(tmp_dir)
+ src_zip = File.join(root_dir, "Examples", "Example-iOS.zip")
+ dst_zip = File.join(tmp_dir, "Example-iOS.zip")
+ FileUtils.cp(src_zip, dst_zip)
+
+ unzip_file(dst_zip, tmp_dir)
+ File.join(tmp_dir, "Example-iOS", "Example-iOS.xcodeproj")
+ end
+
+ def test
+ project_path = generate_empty_project_files
+ target_name = "Example-iOS"
+ test_target_name = "Tests"
+
+ puts "\n\n"
+
+ project = GHUnit::Project.open(project_path, target_name, test_target_name)
+ assert project.create_test_target
+
+ # Run again, should only update
+ project = GHUnit::Project.open(project_path, target_name, test_target_name)
+ assert project.create_test_target
+
+ # Write a podfile pointing at ourselves
+ podfile_content =<<-EOS
+platform :ios, '7.0'
+
+target :Tests do
+ pod 'GHUnit', :path => "../../../../"
+end
+EOS
+ File.open("Podfile", "w") { |f| f.write(podfile_content) }
+
+ system("pod install")
+ system("open #{tmp_dir}/Example-iOS/Example-iOS.xcworkspace")
+ end
+
+end
Please sign in to comment.
Something went wrong with that request. Please try again.