Base fixes and test harness
This commit is contained in:
Executable
+213
@@ -0,0 +1,213 @@
|
||||
#!/bin/bash
|
||||
# Portfolio Journal Test Runner
|
||||
# Usage: ./Scripts/run_tests.sh [options]
|
||||
#
|
||||
# Options:
|
||||
# --unit Run unit tests only (default)
|
||||
# --ui Run UI tests only
|
||||
# --all Run all tests
|
||||
# --coverage Generate code coverage report
|
||||
# --device Specify simulator device (default: iPhone 17)
|
||||
# --help Show this help message
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
PROJECT_PATH="PortfolioJournal.xcodeproj"
|
||||
SCHEME="PortfolioJournal"
|
||||
DEFAULT_DEVICE="iPhone 17"
|
||||
DERIVED_DATA_PATH="$HOME/Library/Developer/Xcode/DerivedData/PortfolioJournal-Tests"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Parse arguments
|
||||
RUN_UNIT=true
|
||||
RUN_UI=false
|
||||
COVERAGE=false
|
||||
DEVICE="$DEFAULT_DEVICE"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--unit)
|
||||
RUN_UNIT=true
|
||||
RUN_UI=false
|
||||
shift
|
||||
;;
|
||||
--ui)
|
||||
RUN_UNIT=false
|
||||
RUN_UI=true
|
||||
shift
|
||||
;;
|
||||
--all)
|
||||
RUN_UNIT=true
|
||||
RUN_UI=true
|
||||
shift
|
||||
;;
|
||||
--coverage)
|
||||
COVERAGE=true
|
||||
shift
|
||||
;;
|
||||
--device)
|
||||
DEVICE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Portfolio Journal Test Runner"
|
||||
echo ""
|
||||
echo "Usage: ./Scripts/run_tests.sh [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --unit Run unit tests only (default)"
|
||||
echo " --ui Run UI tests only"
|
||||
echo " --all Run all tests"
|
||||
echo " --coverage Generate code coverage report"
|
||||
echo " --device Specify simulator device (default: iPhone 17)"
|
||||
echo " --help Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Print banner
|
||||
echo -e "${BLUE}"
|
||||
echo "╔══════════════════════════════════════════╗"
|
||||
echo "║ Portfolio Journal Test Runner ║"
|
||||
echo "╚══════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
|
||||
# Check if project exists
|
||||
if [ ! -d "$PROJECT_PATH" ]; then
|
||||
echo -e "${RED}Error: Project not found at $PROJECT_PATH${NC}"
|
||||
echo "Make sure you're running this script from the project root directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build test arguments
|
||||
BUILD_ARGS=(
|
||||
-project "$PROJECT_PATH"
|
||||
-scheme "$SCHEME"
|
||||
-destination "platform=iOS Simulator,name=$DEVICE"
|
||||
-derivedDataPath "$DERIVED_DATA_PATH"
|
||||
)
|
||||
|
||||
if [ "$COVERAGE" = true ]; then
|
||||
BUILD_ARGS+=(-enableCodeCoverage YES)
|
||||
fi
|
||||
|
||||
# Function to run tests
|
||||
run_tests() {
|
||||
local test_type=$1
|
||||
local test_target=$2
|
||||
|
||||
echo -e "${YELLOW}Running $test_type tests...${NC}"
|
||||
echo "Device: $DEVICE"
|
||||
echo ""
|
||||
|
||||
if xcodebuild test "${BUILD_ARGS[@]}" -only-testing:"$test_target" 2>&1 | xcpretty --color; then
|
||||
echo -e "${GREEN}✅ $test_type tests passed!${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}❌ $test_type tests failed!${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run all tests without filtering
|
||||
run_all_tests() {
|
||||
echo -e "${YELLOW}Running all tests...${NC}"
|
||||
echo "Device: $DEVICE"
|
||||
echo ""
|
||||
|
||||
if xcodebuild test "${BUILD_ARGS[@]}" 2>&1 | xcpretty --color; then
|
||||
echo -e "${GREEN}✅ All tests passed!${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}❌ Some tests failed!${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if xcpretty is available
|
||||
if ! command -v xcpretty &> /dev/null; then
|
||||
echo -e "${YELLOW}Warning: xcpretty not found. Install with: gem install xcpretty${NC}"
|
||||
echo "Running tests without pretty output..."
|
||||
echo ""
|
||||
|
||||
# Run without xcpretty
|
||||
run_tests_raw() {
|
||||
if [ "$RUN_UNIT" = true ] && [ "$RUN_UI" = true ]; then
|
||||
xcodebuild test "${BUILD_ARGS[@]}"
|
||||
elif [ "$RUN_UNIT" = true ]; then
|
||||
xcodebuild test "${BUILD_ARGS[@]}" -only-testing:PortfolioJournalTests
|
||||
elif [ "$RUN_UI" = true ]; then
|
||||
xcodebuild test "${BUILD_ARGS[@]}" -only-testing:PortfolioJournalUITests
|
||||
fi
|
||||
}
|
||||
|
||||
if run_tests_raw; then
|
||||
echo -e "${GREEN}✅ Tests passed!${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}❌ Tests failed!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
EXIT_CODE=0
|
||||
|
||||
if [ "$RUN_UNIT" = true ] && [ "$RUN_UI" = true ]; then
|
||||
run_all_tests || EXIT_CODE=1
|
||||
elif [ "$RUN_UNIT" = true ]; then
|
||||
run_tests "Unit" "PortfolioJournalTests" || EXIT_CODE=1
|
||||
elif [ "$RUN_UI" = true ]; then
|
||||
run_tests "UI" "PortfolioJournalUITests" || EXIT_CODE=1
|
||||
fi
|
||||
|
||||
# Generate coverage report if requested
|
||||
if [ "$COVERAGE" = true ] && [ $EXIT_CODE -eq 0 ]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Generating code coverage report...${NC}"
|
||||
|
||||
COVERAGE_PATH="$DERIVED_DATA_PATH/Build/ProfileData"
|
||||
|
||||
if [ -d "$COVERAGE_PATH" ]; then
|
||||
# Find the profdata file
|
||||
PROFDATA=$(find "$COVERAGE_PATH" -name "*.profdata" | head -1)
|
||||
|
||||
if [ -n "$PROFDATA" ]; then
|
||||
echo "Coverage data found at: $PROFDATA"
|
||||
echo ""
|
||||
echo "To view detailed coverage:"
|
||||
echo " xcrun llvm-cov report \\"
|
||||
echo " \"$DERIVED_DATA_PATH/Build/Products/Debug-iphonesimulator/PortfolioJournal.app/PortfolioJournal\" \\"
|
||||
echo " -instr-profile=\"$PROFDATA\""
|
||||
else
|
||||
echo -e "${YELLOW}No coverage data found. Make sure tests ran successfully.${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}Coverage directory not found.${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo -e "${GREEN}════════════════════════════════════════════${NC}"
|
||||
echo -e "${GREEN} All tests completed successfully! 🎉 ${NC}"
|
||||
echo -e "${GREEN}════════════════════════════════════════════${NC}"
|
||||
else
|
||||
echo -e "${RED}════════════════════════════════════════════${NC}"
|
||||
echo -e "${RED} Some tests failed. Please review above. ${NC}"
|
||||
echo -e "${RED}════════════════════════════════════════════${NC}"
|
||||
fi
|
||||
|
||||
exit $EXIT_CODE
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Script to add test targets to the Xcode project
|
||||
# Usage: ruby Scripts/setup_tests.rb
|
||||
#
|
||||
# Prerequisites:
|
||||
# gem install xcodeproj
|
||||
|
||||
require 'xcodeproj'
|
||||
|
||||
PROJECT_PATH = 'PortfolioJournal.xcodeproj'
|
||||
UNIT_TEST_TARGET_NAME = 'PortfolioJournalTests'
|
||||
UNIT_TEST_BUNDLE_ID = 'com.alexandrevazquez.PortfolioJournalTests'
|
||||
|
||||
def main
|
||||
puts "Opening project at #{PROJECT_PATH}..."
|
||||
project = Xcodeproj::Project.open(PROJECT_PATH)
|
||||
|
||||
# Check if test target already exists
|
||||
if project.targets.any? { |t| t.name == UNIT_TEST_TARGET_NAME }
|
||||
puts "Test target '#{UNIT_TEST_TARGET_NAME}' already exists. Skipping creation."
|
||||
return
|
||||
end
|
||||
|
||||
puts "Creating unit test target..."
|
||||
|
||||
# Find the main app target
|
||||
main_target = project.targets.find { |t| t.name == 'PortfolioJournal' }
|
||||
unless main_target
|
||||
puts "Error: Could not find main app target 'PortfolioJournal'"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Create the unit test target
|
||||
test_target = project.new_target(
|
||||
:unit_test_bundle,
|
||||
UNIT_TEST_TARGET_NAME,
|
||||
:ios,
|
||||
'17.6',
|
||||
main_target
|
||||
)
|
||||
|
||||
# Configure build settings
|
||||
test_target.build_configurations.each do |config|
|
||||
config.build_settings['BUNDLE_LOADER'] = '$(TEST_HOST)'
|
||||
config.build_settings['TEST_HOST'] = '$(BUILT_PRODUCTS_DIR)/PortfolioJournal.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/PortfolioJournal'
|
||||
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = UNIT_TEST_BUNDLE_ID
|
||||
config.build_settings['SWIFT_VERSION'] = '5.0'
|
||||
config.build_settings['CODE_SIGN_STYLE'] = 'Automatic'
|
||||
config.build_settings['DEVELOPMENT_TEAM'] = '2825Q76T7H'
|
||||
config.build_settings['INFOPLIST_FILE'] = ''
|
||||
config.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
|
||||
config.build_settings['SWIFT_EMIT_LOC_STRINGS'] = 'NO'
|
||||
config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = '$(inherited)'
|
||||
config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = [
|
||||
'$(inherited)',
|
||||
'@executable_path/Frameworks',
|
||||
'@loader_path/Frameworks'
|
||||
]
|
||||
end
|
||||
|
||||
# Add test target dependency on main target
|
||||
test_target.add_dependency(main_target)
|
||||
|
||||
# Create file references for test files
|
||||
tests_group = project.main_group.find_subpath('PortfolioJournalTests', true)
|
||||
tests_group.set_source_tree('<group>')
|
||||
tests_group.set_path('PortfolioJournalTests')
|
||||
|
||||
# Find all test Swift files
|
||||
test_files_path = File.join(File.dirname(PROJECT_PATH), 'PortfolioJournalTests')
|
||||
if Dir.exist?(test_files_path)
|
||||
Dir.glob("#{test_files_path}/**/*.swift").each do |file_path|
|
||||
relative_path = file_path.sub("#{test_files_path}/", '')
|
||||
|
||||
# Create subgroups as needed
|
||||
path_components = relative_path.split('/')
|
||||
current_group = tests_group
|
||||
|
||||
path_components[0...-1].each do |component|
|
||||
subgroup = current_group.find_subpath(component, true)
|
||||
subgroup.set_source_tree('<group>')
|
||||
current_group = subgroup
|
||||
end
|
||||
|
||||
# Add file reference
|
||||
file_name = path_components.last
|
||||
file_ref = current_group.new_file(file_path)
|
||||
test_target.source_build_phase.add_file_reference(file_ref)
|
||||
end
|
||||
end
|
||||
|
||||
puts "Saving project..."
|
||||
project.save
|
||||
|
||||
puts "✅ Test target '#{UNIT_TEST_TARGET_NAME}' created successfully!"
|
||||
puts ""
|
||||
puts "Next steps:"
|
||||
puts "1. Open Xcode and build the project"
|
||||
puts "2. Run tests with: xcodebuild test -scheme PortfolioJournal -destination 'platform=iOS Simulator,name=iPhone 17'"
|
||||
puts " Or use: make test"
|
||||
end
|
||||
|
||||
begin
|
||||
main
|
||||
rescue LoadError => e
|
||||
puts "Error: xcodeproj gem not found."
|
||||
puts "Install it with: gem install xcodeproj"
|
||||
puts ""
|
||||
puts "Alternatively, add the test target manually in Xcode:"
|
||||
puts "1. File > New > Target > iOS Unit Testing Bundle"
|
||||
puts "2. Name it 'PortfolioJournalTests'"
|
||||
puts "3. Add the test files from PortfolioJournalTests folder"
|
||||
exit 1
|
||||
rescue => e
|
||||
puts "Error: #{e.message}"
|
||||
puts e.backtrace.first(5).join("\n")
|
||||
exit 1
|
||||
end
|
||||
Reference in New Issue
Block a user