Xcode UI test - swipeRight() not working after tearDown - swift

I have a logout function that gets called during every tearDown(), but does not work when called this way. If I call the same logout function during the test, it works fine. I'm wondering what are the behaviors of XCUI testing during teardown, are there limitations? I tried debugging and calling app.swipeRight() using the lldb (espression->write code)...
-------
Navbar.swift
-------
import XCTest
import Foundation
class NavbarTest: XCTestCaseLib{
override func setUp()
{
super.setUp()
continueAfterFailure = false
}
override func tearDown()
{
logout()
super.tearDown()
}
func testSideBar_STAGING(){
//...<test code that executes no problem>
//...
}
}
-----
XCTestCaseLib.swift
------
import XCTest
import Foundation
class XCTestCaseLib: XCTestCase {
let app = XCUIApplication()
func logout() {
app.swipeRight()
...
}

From the code you've posted, it appears to be your imports (I'm assuming here that these classes are in different files, otherwise your inheritance is ambiguous). If I'm mistaken please update your question to include your file structure. Play around with your imports and inheritance.
I believe you just need to import XCTest on your NavbarTest class

Related

Inherit tests from a common XCTestCase from a Swift package

Consider the following:
A Swift package Feature has a protocol Component and a couple of implementations FooComponent, BarComponent, etc.
The package has its own tests FeatureTests and the Component's are tested in a way, that individual implementations inherit a single test case in order to test the common expectations of a Component:
import XCTest
#testable import Feature
class ComponentTests: XCTestCase {
var sut: Component!
override class var defaultTestSuite: XCTestSuite {
XCTestSuite(name: "EventStorageService Interface Tests Excluded")
}
func test_common() { }
}
...
class FooComponentTests: ComponentTests {
override func setUpWithError() throws {
try super.setUpWithError()
sut = FooComponent()
}
override class var defaultTestSuite: XCTestSuite {
XCTestSuite(forTestCaseClass: Self.self)
}
func test_specific() { }
}
class BarComponentTests: ComponentTests {
override func setUpWithError() throws {
try super.setUpWithError()
sut = BarComponent()
}
...
This all works really nicely within the Swift package.
Now let's consider the app App injects its own custom Component implementation and also wants to test it and benefit from the already written common tests.
import XCTest
#testable import App
#testable import Feature
class CustomComponentTests: ComponentTests { // Error: Cannot find type 'ComponentTests' in scope
...
Of course the above does not work as the compiler does not find ComponentTests. And importing FeatureTests also fails.
import XCTest
#testable import App
#testable import FeatureTests // Error: No such module 'FeatureTests'
class CustomComponentTests: ComponentTests {
...
Does anyone have an idea how to achieve the desired outcome (i.e. inherit common tests for the protocol defined within the lib in order to not duplicate the test code)?

Swift Error - Method Does not override any method from its superclass

I am running into an issue where when I am attempting to override a function it is telling me that there is no method in the superclass. The subclass is in an XCTest. When I subclass in the regular project it works perfectly but the XCTest does not work for some reason Below is the Code
SuperClass
class BackupServerCell: UITableViewCell {
#IBOutlet var serverNameLabel: UILabel!
#IBOutlet var serverDescriptionLabel: UILabel!
func configCell(with server: VeeamBackupServer) {
}
}
Subclass - Located in the XCTest file
class MockBackupServerCell : BackupServerCell {
var configCellGotCalled = false
override func configCell(with server: VeeamBackupServer) {
configCellGotCalled = true
}
}
When you are working on a Test target, its sometime needed to import your main project.
Let's say your project is named 'MyAwesomeProject', just need to add this line in your test file:
#testable import MyAwesomeProject
To obtain something like this:
import XCTest
#testable import MyAwesomeProject
class TestStaticQueries: XCTestCase {
// Add your test methods here.
}
#DDelforge, was partially correct. I had to add the BackupServerCell class, to the Test Target. Not sure why this class is different, but hey, it works.
Thank you all

Is it possible to hide classes from ui tests

I have a few helper classes like UnlockedTestCase that configure my app for special scenario tests.
Theses classes show up in the test navigator without tests.
Is there a way to mark then as "not test classes" in order for them to be ignored by the test navigator?
UPDATE: Sample code:
class UnlockedTestCase: XCTestCase {
var app = XCUIApplication()
override func setUp() {
super.setUp()
continueAfterFailure = false
app.launchArguments = ["uiTesting", "unlock"]
app.launch()
}
}
A test would then be written as:
class UnlockedUITests: UnlockedTestCase {
func testButton() {
XCTAssers(app.buttons["SomeButtonInTheUnlockedState"].exists)
}
}
No, there is not a way to exclude that kind of class from the test navigator without losing the ease of defining the setUp(), as the way that it discovers test case classes is simplistic, and from the point of view of the navigator, you could add test cases to the parent/helper class at any moment since it is an XCTestCase descendant.
There is no protocol for 'helper' or 'abstract-only' classes which support inheritance in the way that you require, since inheritance from XCTestCase is required for the automatic discovery and usage of tests and test hooks like setUp().
If you really want to get rid of your helper entities from the test navigator, you could abstract them into protocols with extensions where Self: XCTestCase (to allow you access to XCTestCase's interface in the extension), have your test class conform to them, and override setUp() in the class where your tests are.
protocol UnlockableTest {}
extension UnlockableTest where Self: XCTestCase {
func unlockSetUp() {
continueAfterFailure = false
app.launchArguments = ["uiTesting", "unlock"]
app.launch()
}
}
class UnlockedUITests: XCTestCase, UnlockableTest {
var app = XCUIApplication()
override func setUp() {
super.setUp()
unlockSetUp()
}
func testButton() {
XCTAssert(app.buttons["SomeButtonInTheUnlockedState"].exists)
}
}
However, I think the simplicity and convenience of your current approach is the preferable compromise. Protocols also can't contain stored properties though, so in order to get the benefit of a stored property, you'd need to add the app property to every XCTestCase descendant too.
You can do this with Swift packages now, if your tests are in a Swift Package then you can have a helper module that contains your base classes and these will not be added to the sidebar as empty test cases.
You can mix an xcodeproj with a local to the source folder swift package to facilitate this, and in general I would personally recommend this as it improves build times and allows you to make your codebase more modular with granular access control.
Assuming the following structure:
MyTestHelperClassName: XCTestCase {
//... your helper methods
}
Remove its subclass declaration of XCTestCase
i.e the : XCTestCase part
Then it will not appear in the "Test Navigator"

Unable to access Main Target Methods when Adding Tests to OSX Project in Swift

I have tried adding a testing bundle to my Project which seems to have succeeded.
However when I try to create instances of the Classes in my main project- I am unable to see them.
The Project seems to build fine - but I can' instantiate any of the test objects
Any ideas how to access them
Example Class to Test:
class EmailHelper: NSObject {
func generateEmailBody (greeting: String, bodyContent: String) -> String {
//Content goes in here
return message
}
}
import XCTest
class MyProject_DesktopTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// The Test would go in here but I can't seem to resolve EmailHelper class- it generates a lint error
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
}
I managed to get it working by adding Testable to the top of the class( This appears to be OSX specific issue)
import XCTest
#testable import MyProjectName // <--- This was the missing bit.... :)
class MyProject_DesktopTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// The Test would go in here but I can't seem to resolve EmailHelper class- it generates a lint error
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
}
Also be sure to clean your project after adding it an it seems to work.

Variable declaration inside of class in Swift

I'm new in swift automated testing with XCTest framework.
In my work I faced with correct arrangement some parts of code inside of test
Please explain the difference between variable declaration in the beginning of the class and in the certain function. Which way is preferred?
Var.1
class someClass: XCTestCase {
let app = XCUIApplication()
func someFunc {
print (app.debugdescription)
}
}
Var. 2
class someClass: XCTestCase {
func someFunc {
let app = XCUIApplication()
print (app.debugdescription)
}
}
Var. 1 gives you the ability to configure your XCUIApplication in setup() and use it in the tests. Like this:
class someClass: XCTestCase {
var app: XCUIApplication!
func setUp {
app = XCUIApplication()
app.launchArguments.append("launchArgument")
setupSnapshot(app)
app.launch()
}
func test1 {
XCTAssertNotNil(app)
}
func test2 {
XCTAssertNotNil(app)
}
}
With Var. 2 you can setup your app differently in each test. Like this:
class someClass: XCTestCase {
func test1 {
let app = XCUIApplication()
app.launchArguments.append("withTestUser")
app.launch()
XCTAssertNotNil(app)
}
func test2 {
let app = XCUIApplication()
app.launchArguments.append("withNoData")
app.launch()
XCTAssertNotNil(app)
}
}
Both ways are possible but var 2 is preferred. For var 1 solution consider the following scenario:
class State {
var val: Int = 0
}
class TestClass: XCTestCase {
let state = State()
func test1() {
state.val = 5
XCTAssertEqual(5, state.val)
}
func test2() {
XCTAssertEqual(0, state.val)
}
}
This way result depends on which test will run first. If test2 will be the first then both tests will succeed. Other way, second test will fail.
For var 2 solution
class TestClass: XCTestCase {
func test1() {
let state = State()
state.val = 5
XCTAssertEqual(5, state.val)
}
func test2() {
let state = State()
XCTAssertEqual(0, state.val)
}
}
both tests succeeds no matter what test will run firstly. This makes var 2 solution preferred in most scenarios.
There is a case when var 1 is more convenient than var 2. It is when SUT have many dependencies and you have to copy and paste creation code for them in each test. Then you can declare dependencies as a class variables, but you must use test setUp (and possibly a tearDown) to ensure that their states is refreshed before each test
class TestClass: XCTestCase {
var dep1: Dependency1!
var dep2: Dependency2!
var sut: SUT!
func setUp() {
dep1 = Dependency1()
dep2 = Dependency2()
sut = SUT(dep1, dep2)
}
}
Variable declaration as Class level or the Function level is same as in other programming languages, so it would be great if you understand their basic principle.
Class level variable means that this variable can be accessed throughout the class, that means it can be used in any function of the same class. It also means that if you make the class as public, and that variable as public, then once the class is initialized it could be accessed within your program in other classes. Usually they could create memory issues if you don't manage them properly as they stay in the memory when the class itself is within the memory.
Function level variable can only be accessed within that specific function and not outside that function whether it's the same class or a different class, they have no reference outside their function. Usually they don't create memory issues in your whole program as these variables leave the memory when that function is completely executed.